├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── Changelog.md
├── LICENSE.txt
├── Manual
├── AzulPatcher4600_equivalent.plist
├── FAQ.Chart.md
├── FAQ.GeForce.en.md
├── FAQ.IntelHD.cn.md
├── FAQ.IntelHD.en.md
├── FAQ.OldPlugins.en.md
├── FAQ.Radeon.en.md
├── FAQ.Radeon.ru.md
├── FAQ.Shiki.en.md
├── FAQ.Shiki.ru.md
├── FAQ.Shiki.zh_CN.md
├── Img
│ ├── Clover1.png
│ ├── Clover2.png
│ ├── WhiskeyLake.png
│ ├── basic.png
│ ├── bin.png
│ ├── bios.png
│ ├── cfl-r_igpu.png
│ ├── connector.png
│ ├── dGPU_off.png
│ ├── dpcd_mlr.png
│ ├── dvmt.png
│ ├── edid.png
│ ├── hdmi20.png
│ ├── hsw_igpu.png
│ ├── ifbt.png
│ ├── ivy_imei.png
│ ├── kbl-r_igpu.png
│ ├── kbl.png
│ ├── lspcon.png
│ ├── lspcon_debug.png
│ ├── max-pixel-clock.png
│ ├── sem.png
│ ├── snb.png
│ ├── snb_igpu.png
│ ├── snb_imei.png
│ ├── vda.png
│ └── vda2.png
├── IntelFramebuffer.bt
├── NVCAP.bt
├── Sample.dsl
├── edid-gen.sh
└── reference.cpp
├── Prebuilt
├── BoardHash
├── WhateverName.app
│ └── Contents
│ │ ├── Info.plist
│ │ ├── MacOS
│ │ ├── WhateverName
│ │ └── libWhateverName.dylib
│ │ └── Resources
│ │ └── icon.icns
├── gpuinfo
└── libHookMac.dylib
├── README.md
├── ResourceConverter
├── generate.sh
└── main.mm
├── Resources
└── Patches.plist
├── Tools
├── BoardHash
│ ├── BoardHash.c
│ └── build.tool
├── GPUInfo
│ ├── build.tool
│ └── gpuinfo.c
├── HookMac
│ ├── HookMac.c
│ ├── build.tool
│ ├── rd_route.c
│ └── rd_route.h
├── WhateverName
│ ├── WhateverName.app
│ │ └── Contents
│ │ │ ├── Info.plist
│ │ │ ├── MacOS
│ │ │ └── WhateverName
│ │ │ └── Resources
│ │ │ └── icon.icns
│ ├── WhateverName.mm
│ ├── build.tool
│ ├── rd_route.c
│ └── rd_route.h
└── dump_platformlist.sh
├── WhateverGreen.xcodeproj
└── project.pbxproj
└── WhateverGreen
├── Info.plist
├── kern_agdc.hpp
├── kern_atom.hpp
├── kern_cdf.cpp
├── kern_cdf.hpp
├── kern_con.hpp
├── kern_fb.hpp
├── kern_guc.cpp
├── kern_guc.hpp
├── kern_igfx.cpp
├── kern_igfx.hpp
├── kern_igfx_backlight.cpp
├── kern_igfx_backlight.hpp
├── kern_igfx_clock.cpp
├── kern_igfx_debug.cpp
├── kern_igfx_i2c_aux.cpp
├── kern_igfx_kexts.cpp
├── kern_igfx_kexts.hpp
├── kern_igfx_lspcon.cpp
├── kern_igfx_lspcon.hpp
├── kern_igfx_memory.cpp
├── kern_igfx_pm.cpp
├── kern_model.cpp
├── kern_ngfx.cpp
├── kern_ngfx.hpp
├── kern_ngfx_asm.S
├── kern_nvhda.cpp
├── kern_nvhda.hpp
├── kern_rad.cpp
├── kern_rad.hpp
├── kern_shiki.cpp
├── kern_shiki.hpp
├── kern_start.cpp
├── kern_unfair.cpp
├── kern_unfair.hpp
├── kern_weg.cpp
└── kern_weg.hpp
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | pull_request:
6 | workflow_dispatch:
7 | release:
8 | types: [published]
9 |
10 | env:
11 | PROJECT_TYPE: KEXT
12 |
13 | jobs:
14 | build:
15 | name: Build
16 | runs-on: macos-latest
17 | env:
18 | JOB_TYPE: BUILD
19 | steps:
20 | - uses: actions/checkout@v4
21 | - uses: actions/checkout@v4
22 | with:
23 | repository: acidanthera/MacKernelSDK
24 | path: MacKernelSDK
25 | - name: CI Bootstrap
26 | run: |
27 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/ocbuild/master/ci-bootstrap.sh) && eval "$src" || exit 1
28 | - name: Lilu Bootstrap
29 | run: |
30 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/Lilu/master/Lilu/Scripts/bootstrap.sh) && eval "$src" || exit 1
31 |
32 | - run: xcodebuild -jobs 1 -configuration Debug
33 | - run: xcodebuild -jobs 1 -configuration Release
34 |
35 | - name: Upload to Artifacts
36 | uses: actions/upload-artifact@v4
37 | with:
38 | name: Artifacts
39 | path: build/*/*.zip
40 | - name: Upload to Release
41 | if: github.event_name == 'release'
42 | uses: svenstaro/upload-release-action@v2
43 | with:
44 | repo_token: ${{ secrets.GITHUB_TOKEN }}
45 | file: build/*/*.zip
46 | tag: ${{ github.ref }}
47 | file_glob: true
48 |
49 | analyze-clang:
50 | name: Analyze Clang
51 | runs-on: macos-latest
52 | env:
53 | JOB_TYPE: ANALYZE
54 | steps:
55 | - uses: actions/checkout@v4
56 | - uses: actions/checkout@v4
57 | with:
58 | repository: acidanthera/MacKernelSDK
59 | path: MacKernelSDK
60 | - name: CI Bootstrap
61 | run: |
62 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/ocbuild/master/ci-bootstrap.sh) && eval "$src" || exit 1
63 | - name: Lilu Bootstrap
64 | run: |
65 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/Lilu/master/Lilu/Scripts/bootstrap.sh) && eval "$src" || exit 1
66 |
67 | - run: xcodebuild analyze -quiet -scheme WhateverGreen -configuration Debug CLANG_ANALYZER_OUTPUT=plist-html CLANG_ANALYZER_OUTPUT_DIR="$(pwd)/clang-analyze" && [ "$(find clang-analyze -name "*.html")" = "" ]
68 | - run: xcodebuild analyze -quiet -scheme WhateverGreen -configuration Release CLANG_ANALYZER_OUTPUT=plist-html CLANG_ANALYZER_OUTPUT_DIR="$(pwd)/clang-analyze" && [ "$(find clang-analyze -name "*.html")" = "" ]
69 |
70 | analyze-coverity:
71 | name: Analyze Coverity
72 | runs-on: macos-latest
73 | env:
74 | JOB_TYPE: COVERITY
75 | if: github.repository_owner == 'acidanthera' && github.event_name != 'pull_request'
76 | steps:
77 | - uses: actions/checkout@v4
78 | - uses: actions/checkout@v4
79 | with:
80 | repository: acidanthera/MacKernelSDK
81 | path: MacKernelSDK
82 | - name: CI Bootstrap
83 | run: |
84 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/ocbuild/master/ci-bootstrap.sh) && eval "$src" || exit 1
85 | - name: Lilu Bootstrap
86 | run: |
87 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/Lilu/master/Lilu/Scripts/bootstrap.sh) && eval "$src" || exit 1
88 |
89 | - name: Run Coverity
90 | run: |
91 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/ocbuild/master/coverity/covstrap.sh) && eval "$src" || exit 1
92 | env:
93 | COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
94 | COVERITY_SCAN_EMAIL: ${{ secrets.COVERITY_SCAN_EMAIL }}
95 | COVERITY_BUILD_COMMAND: xcodebuild -configuration Release
96 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | DerivedData
3 | Lilu.kext
4 | xcshareddata
5 | xcuserdata
6 | project.xcworkspace
7 | build
8 | WhateverGreen/kern_resources.cpp
9 | WhateverGreen/kern_resources.hpp
10 | Tools/BoardHash/BoardHash
11 | Tools/GPUInfo/gpuinfo
12 | Tools/HookMac/libHookMac.dylib
13 | Tools/WhateverName/WhateverName.app/Contents/MacOS/libWhateverName.dylib
14 | .svace-dir
15 | cov-int
16 | /MacKernelSDK
17 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2018, vit9696
2 |
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 |
9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10 |
11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14 |
--------------------------------------------------------------------------------
/Manual/AzulPatcher4600_equivalent.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Devices
6 |
7 | Properties
8 |
9 | PciRoot(0x0)/Pci(0x2,0x0)
10 |
11 | AAPL,ig-platform-id
12 | BgAmCg==
13 | device-id
14 | EgQAAA==
15 | framebuffer-con1-enable
16 | AQAAAA==
17 | framebuffer-con1-pipe
18 | EgAAAA==
19 | framebuffer-con1-type
20 | AAgAAA==
21 | framebuffer-con2-alldata
22 | /wAAAAEAAABAAAAA
23 | framebuffer-con2-enable
24 | AQAAAA==
25 | framebuffer-cursormem
26 | AACQAA==
27 | framebuffer-memorycount
28 | AgAAAA==
29 | framebuffer-patch-enable
30 | AQAAAA==
31 | framebuffer-portcount
32 | AgAAAA==
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/Manual/FAQ.Chart.md:
--------------------------------------------------------------------------------
1 | # DRM Compatibility Chart for 10.15
2 |
3 | | Configuration | Mode | iTunes Trailers | iTunes Movies | TV+ | Prime Trailers | Prime/Netflix | IQSV |
4 | | :-------------- | :------------- | :-------------- | :------------ | :--- | :------------- | ------------- | ---- |
5 | | AMD+IGPU, IM/MM | `shikigva=16` | SW1 | SW2 | HW4 | HW | NO | OK |
6 | | AMD+IGPU, IM/MM | `shikigva=80` | SW1 | SW2 | HW4 | HW3 | HW3 | OK |
7 | | AMD, IMP/MP | | SW1 | SW2 | HW4 | HW3 | HW3 | NO |
8 | | AMD, IMP/MP | `shikigva=128` | HW1 | HW2 | HW4 | HW3 | HW3 | NO |
9 | | NV+IGPU, IM/MM | | SW1 | SW2 | NO | HW | NO | OK |
10 | | NV, IMP/MP | `shikigva=256` | SW1 | SW2 | SW3 | HW | NO | NO |
11 | | IGPU, IM/MM | | SW1 | NO | NO | HW | NO | OK |
12 |
13 | - SW - software unencrypted decoder, works everywhere
14 | - HW - hardware unencrypted decoder, works with any compatible GPU
15 | - SW1 - software FairPlay 1.0 decoder (CoreFP)
16 | - SW2 - software FairPlay 1.0 decoder (CoreFP), requires HDCP
17 | - SW3 - software FairPlay 4.0 decoder (CoreLSKD), requires HDCP and no IGPU
18 | - HW1 - hardware FairPlay 1.0 decoder (CoreFP), requires select AMD GPUs
19 | - HW2 - hardware FairPlay 1.0 decoder (CoreFP), requires HDCP and select AMD GPUs
20 | - HW3 - hardware FairPlay 2.0/3.0 decoder (CoreLSKDMSE), requires HDCP and select AMD GPUs
21 | - HW4 - hardware FairPlay 4.0 decoder (CoreLSKD), requires HDCP and select AMD GPUs
22 |
23 | - IM/MM - iMac/Macmini models with IGPU, IGPU must have connector-less framebuffer-id when AMD/NV is used.
24 | - IMP/MP - iMacPro/MacPro models without IGPU.
25 | - Other configurations are used at your own risk, use `-shikioff` to disable modifications
26 |
27 | # DRM Compatibility on macOS 11+
28 |
29 | Things to keep in mind:
30 |
31 | - All kinds of software DRM decoders were removed from macOS 11+
32 | - All kinds of legacy hardware DRM decoders (e.g. NVIDIA VP3) were removed from macOS 11+
33 | - WhateverGreen Shiki functionality is not planned for inclusion for macOS 11+
34 | - Only IGPU-free Mac models allow for full DRM content access given a compatible AMD GPU video decoder
35 | - For old CPUs (e.g. Xeons or Core 2 Quad) and supported AMD GPUs injecting `unfairgva` with `<01 00 00 00>` value is required for streaming DRM.
36 |
37 | More about `unfairgva` bitmask:
38 | 1 -> Enables DRM on old CPUID
39 | 2 -> Relax HDCP requirements
40 | 4 -> Inject the iMacPro1,1 board ID and therefore forces AMD video decoder/encoder
41 |
42 | - AMD GPU video decoder preference can be chosen through preferences overrides for some types of DRM content (like Apple TV and iTunes movie streaming). This preference may not always be compatible with the rest of the operating system and may cause problems with other ways of hardware media decoding and encoding. For this reason such an override is not recommended for daily use and shall only be enabled on demand.
43 |
44 | List of overrides:
45 | - `defaults write com.apple.AppleGVA gvaForceAMDKE -boolean yes` forces AMD DRM decoder for streaming services (like Apple TV and iTunes movie streaming)
46 | - `defaults write com.apple.AppleGVA gvaForceAMDAVCDecode -boolean yes` forces AMD AVC accelerated decoder
47 | - `defaults write com.apple.AppleGVA gvaForceAMDAVCEncode -boolean yes` forces AMD AVC accelerated encoder
48 | - `defaults write com.apple.AppleGVA gvaForceAMDHEVCDecode -boolean yes` forces AMD HEVC accelerated decoder
49 | - `defaults write com.apple.AppleGVA disableGVAEncryption -string YES` forces AMD HEVC accelerated decoder
50 | - `defaults write com.apple.coremedia hardwareVideoDecoder -string force` forces hardware accelerated video decoder (for any resolution)
51 | - `defaults write com.apple.coremedia hardwareVideoDecoder -string disable` disables hardware accelerated video decoder (in QuickTime / Apple TV)
52 |
--------------------------------------------------------------------------------
/Manual/FAQ.GeForce.en.md:
--------------------------------------------------------------------------------
1 | # Nvidia GeForce FAQs
2 |
3 | - _What are the system requirements?_
4 | while there are no particular limitations, this FAQ does not include the specific information regarding GPUs before Kepler (i.e. older than 6xx series).
5 | In general it appears to be less convenient to use CPUs newer than Ivy and Haswell with NVIDIA GPUs.
6 | For GPUs newer than Kepler (e.g. Maxwell or Pascal) you need [NVIDIA Web Driver](http://www.nvidia.com/download/driverResults.aspx/125379/en-us). Use `nv_disable=1` boot argument to install it.
7 |
8 | - _What is the general idea?_
9 | If you have builtin Intel GPU, make sure to rename it to IGPU and enable with connector-less frame first. Then choose a most suitable mac model and install WhateverGreen.kext. It also used for hardware video decoding, please read [Shiki FAQ](./FAQ.Shiki.en.md) carefully to get a good understanding.
10 |
11 | - _How to properly choose a mac model?_
12 | If you have Ivy Bridge or Haswell CPU you should go with iMac13,2 or iMac14,2. Otherwise choose the model you prefer, but keep this in mind:
13 | - If you have Intel GPU, especially if Ivy Bridge or newer, choose the model (by `board-id`) that has `forceOfflineRenderer` set to YES (true) in /System/Library/PrivateFrameworks/AppleGVA.framework/Versions/A/Info.plist.
14 | - Models other than iMac13,2 and iMac14,2 require patches, which are though normally automated in WhateverGreen (see below)
15 | - CPUs newer than Haswell require Shiki patches for hardware video decoding (see below).
16 |
17 | - _Why should I use Intel GPU with a connector-less frame?_
18 | Nvidia GPUs newer than 2xx do not implement hardware video decoder in macOS, also starting with 10.13 dual-GPU setups often cause a bootloop. If you absolutely need your IGPU with connector-full frame you will have to determine correct ig-platform-id and `shikigva=1` bootarg OR a model without `forceOfflineRenderer`.
19 | Read the [Shiki FAQ](./FAQ.Shiki.en.md)
20 |
21 | - _How to use Intel GPU with a connector-less frame?_
22 | Please refer to [Shiki FAQ](./FAQ.Shiki.en.md) for full details. You could use SSDT to rename GFX0 to IGPU by creating a proper IGPU device and setting STA of the existing one to Zero:
23 |
24 | ```
25 | Scope (GFX0) {
26 | Name (_STA, Zero) // _STA: Status
27 | }
28 | ```
29 |
30 | - _What patches do I need for mac models other than iMac13,2 and iMac14,2?_
31 | AppleGraphicsDisplayPolicy.kext contains a check against its Info.plist and determines which mode should be used for a specific board-id. It is dependent on the GPU which mode is suitable and is normally determined experimentally. WhateverGreen contains several ways to configure to set power management modes:
32 | - kext patch enforcing `none` into ConfigMap dictionary for system board-id (agdpmod=cfgmap)
33 | - kext patch disabling string comparison (`agdpmod=vit9696`, enabled by default)
34 | - kext patch replacing `board-id` with `board-ix` (`agdpmod=pikera`)
35 |
36 | - _What patches do I need for Maxwell or Pascal GPUs?_
37 | Maxwell GPUs (normally 9xx and some 7xx) no longer supply a correct IOVARendererID to enable hardware video decoder. See more details: [here](https://github.com/vit9696/Shiki/issues/5). You no longer need any changes (e.g. iMac.kext) but WhateverGreen. This fix was added in 1.2.0 branch. Can be switched off by using boot-arg "-ngfxnovarenderer".
38 |
39 | - _What patches do processors newer than Haswell need?_
40 | Apple limits hardware video decoder with NVIDIA to only Haswell and earlier. To get hardware accelerated video decoding you need to patch AppleGVA.framework. To do so you could use [WhateverGreen](https://github.com/acidanthera/WhateverGreen) with `shikigva=4` boot argument. On 10.13 you may currently use a temporary workaround that enables hardware video decoding only for a subset of processes via `shikigva=12` boot argument. Starting with macOS 10.13.4 the problem is gone.
41 |
42 | - _What patches do Pascal GPUs need on 10.12?_
43 | On 10.12 and possibly on 10.13 Pascal GPUs need a team id unlock to avoid glitches like empty transparent windows and so on. This patch is already present in WhateverGreen, and the use of any other kext (e.g. NVWebDriverLibValFix.kext) is not needed.
44 | Can be switched off by using boot-arg "-ngfxlibvalfix".
45 |
46 | - _How can I enable digital (HDMI audio)?_
47 | You must esnure that you do not have any conflicting "fixes" from Clover, SSDT patches, Arbitrary and so on (e.g. FixDisplay, AddHDMI, etc.). AppleALC renames GPU audio device to HDAU, and injects missing layout-id and hda-gfx (starting with onboard-1) properties, and injects audio connectors @0,connector-type - @5,connector-type. Injection can be switched off by using boot-arg "-ngfxnoaudio" or more specific "-ngfxnoaudiocon". You can also use ioreg properties in GPU to disable respective injections: "no-audio-autofix" or "no-audio-fixconn".
48 |
49 | - _How can I partially fix Apple Logo during boot?_
50 | Inject `@X,AAPL,boot-display` GFX0 property with the main screen index instead of X, the value does not matter.
51 |
52 | - _Does WhateverGreen fix visual issues on wakeup with Pascal GPUs?_
53 | Not at the moment. It is also known that HDMI audio may not always work with Pascal GPUs.
54 |
55 | - _HDMI audio device only visible after rescan_
56 | [Jamie](https://sourceforge.net/p/nvidiagraphicsfixup/tickets/9/) found out through linux that nvidia graphics on laptops gtx 1060/1070 specifically,
57 | that the audio device is disabled by default. [Bug description](https://bugs.freedesktop.org/show_bug.cgi?id=75985).
58 | He discovered that when the 0x488 magic bit is not set, the gfx device advertises as non-multifunction.
59 | After the bit is set, the device advertises as multi-function.
60 | So, after setting the magic bit, removing the device will cause Linux to re-probe it during the next rescan
61 | taking note at that point that it is a multi-function device
62 | on linux theres a fix use: setpci -s 01:00.0 0x488.l=0x2000000:0x2000000" on mac os he added:
63 |
64 | ```
65 | Device (PEG0)
66 | {
67 | Name (_ADR, 0x00010000) // _ADR: Address
68 | Method (_PRT, 0, NotSerialized) // _PRT: PCI Routing Table
69 | {
70 | ** Store (One, ^GFX0.NHDA)**
71 | If (PICM)
72 | {
73 | Return (AR01)
74 | }
75 |
76 | Return (PR01)
77 | }
78 | }
79 | ```
80 |
81 | NHDA is declared here:
82 |
83 | ```
84 | Scope (_SB.PCI0.PEG0)
85 | {
86 | Device (GFX0)
87 | {
88 | Name (HDAU, Zero)
89 | OperationRegion (PCI2, SystemMemory, 0xE0100000, 0x0500)
90 | Field (PCI2, DWordAcc, Lock, Preserve)
91 | {
92 | Offset (0x48B),
93 | , 1,
94 | NHDA, 1
95 | }
96 | }
97 | }
98 | ```
99 |
--------------------------------------------------------------------------------
/Manual/FAQ.OldPlugins.en.md:
--------------------------------------------------------------------------------
1 | # Superceded plug-ins nuances
2 |
3 | CoreDisplayFixup.kext is deprecated because it is equivalent to use `enable-hdmi20`= `01000000` in `DeviceProperties` or boot-arg: `-cdfon`
4 |
5 | AzulPatcher4600.kext is deprecated because it is equivalent to use `framebuffer-patch` in `DeviceProperties`
6 | For example, patch fCursorMemorySize=9MB:
7 | `framebuffer-patch-enable` = `01000000`
8 | `framebuffer-cursormem` = `00009000`
9 | [Full equivalent AzulPatcher4600.kext](https://github.com/acidanthera/WhateverGreen/blob/master/Manual/AzulPatcher4600_equivalent.plist)
10 |
11 | IntelGraphicsDVMTFixup.kext is deprecated because it is equivalent to use `framebuffer-patch` in `DeviceProperties`
12 | `framebuffer-patch-enable` = `01000000`
13 | `framebuffer-fbmem` = `00009000`
14 | `framebuffer-stolenmem` = `00003001`
15 |
16 | EnableLidWake.kext is deprecated because it is equivalent to setting `FBAlternatePWMIncrement1/2` bit in flags.
17 |
18 | AppleBacklightFixup.kext is deprecated.
19 | In case of custom AppleBacklight profile if is necessary, add correct profile in `DeviceProperties` `applbkl-name` and `applbkl-data`
20 |
21 | NoVPAJpeg.kext is deprecated.
22 | In case its functionality is needed, add the following boot arguments:
23 | `shikigva=32 shiki-id=Mac-7BA5B2D9E42DDD94`
24 |
--------------------------------------------------------------------------------
/Manual/FAQ.Radeon.en.md:
--------------------------------------------------------------------------------
1 | # AMD Radeon FAQs
2 |
3 | - _When do I need WhateverGreen?_
4 | If you run macOS 10.11 or newer (possibly latest 10.10 as well) with an ATI/AMD GPU 5xxx or newer, you most likely do.
5 | Unfortunately it is not possible to test all the GPUs and their configurations, use at your own risk.
6 |
7 | - _How do I get the debug log?_
8 | Install DEBUG versions of WhateverGreen and Lilu, then add `-wegdbg -liludbg` to the boot arguments. Once you boot run the following command in terminal:
9 | `log show --predicate 'process == "kernel" AND (eventMessage CONTAINS "WhateverGreen" OR eventMessage CONTAINS "Lilu")' --style syslog --source`
10 | If you have macOS 10.11 or earlier, use this command:
11 | `cat /var/log/system.log | egrep '(WhateverGreen|Lilu)'`
12 | Please note that in the case you cannot boot if your problem is specific to the GPU you should be able to get the log via SSH. In this case also check the `kextstat` command output.
13 |
14 | - _What is the state of 10.13 support?_
15 | At the time of the release 10.13 is still being tested, so no support could even be thought about. There exist cases of broken AMD graphics on pre-Nehalem CPU chipsets. If you have older hardware please stay away from using 10.13. For other systems WhateverGreen may work if no drastic changes happen in 10.13.
16 |
17 | - _What are the hardware requirements for WhateverGreen?_
18 | Full UEFI without CSM. You are strongly recommended to flash a UEFI-compatible ROM unless your card already has it. Failing to do so will quite likely result in issues in multi-monitor configurations and possibly even in single-monitor configurations. It may stil work for non-UEFI motherboards, try at your own risk. There are known issues when using 2 or more GPUs in multi-monitor configurations.
19 |
20 | - _How do I flash my GPU?_
21 | You could follow [this guide](https://www.techpowerup.com/forums/threads/amd-ati-flashing-guide.212849/) in flashing your UEFI-enabled ROM. To create a UEFI-enabled ROM for your GPU you could follow [this guide](http://www.win-raid.com/t892f16-AMD-and-Nvidia-GOP-update-No-requests-DIY.html). Note, that there is [a tool](http://www.insanelymac.com/forum/topic/299614-asus-eah6450-video-bios-uefi-gop-upgrade-and-gop-uefi-binary-in-efi-for-many-ati-cards/#entry2042163) for macOS, it could also work, but you will likely have to take care of extra padding.
22 |
23 | - _When should I use a named framebuffer?_
24 | Named framebuffers (Baladi, Futomaki, Lotus, etc.), enabled by "Clover GPU injection" or any other methods should _never ever be used_. This way of GPU injection is a common mistake, preventing automatic configuration of various important GPU parameters. This will inavoidably lead to borked GPU functioning in quite a number of cases.
25 |
26 | - _When and how should I use custom connectors?_
27 | In general automatic controller detection written in Apple kexts creates perfect connectors from your VBIOS. The logic of that can be found in [reference.cpp](./reference.cpp). However, some GPU makers physically create different connectors but leave the VBIOS unchanged. This results in invalid connectors that are incompatible with your GPU. The proper way to fix the issues is to correct the data in VBIOS, however, just providing custom connectors can be easier.
28 | For some GPUs (e.g. 290, 290X and probably some others) WhateverGreen incorporates automatic connector correction that can be enabled via `-raddvi` boot argument. For other GPUs you may specify them as a GPU device property called `connectors`, for example, via SSDT. You could pass your connectors in either 24-byte or 16-byte format, they will be automatically adapted to the running system. If you need to provide more or less connectors than it is detected automatically, you are to specify `connector-count` property as well. Please note that automatically detected connectors appear in the debug log to give you a good start.
29 |
30 | - _How can I change display priority?_
31 | With 7xxx GPUs or newer you could simply add `connector-priority` GPU controller property with sense ids (could be seen in debug log) in the order of their importance. This property may help with black screen issues especially with the multi-monitor configurations.
32 | Without this property specified all the connectors will stay with 0 priority. If there are unspecified connectors they will be ordered by type: LVDS, DVI, HDMI, DP, VGA. Read [SSDT sample](./Sample.dsl) for more details.
33 |
34 | - _What properties should I inject for my GPU?_
35 | Very few! You should inject an `HDAU` device to your GPU controller, `hda-gfx` properties with a corresponding number to the amount of audio codecs you have, and that is basically all. If you need to mask to an unsupported GPU, additionally add `device-id`. It is also recommended to add some cosmetic properties: `AAPL,slot-name` (displayed slot name in system details), `@X,AAPL,boot-display` (boot logo drawing issues), `model` (GPU display name, if detection failed).
36 | While not pretending to be perfect, there is a [SSDT sample](./Sample.dsl) to get the general idea.
37 |
38 | - _What properties should I additionally inject for my MOBILE GPU?_
39 | Mobile AMD GPUs have very few issues but only if they are physically connected to the display (i.e. AMD Switchable Graphics users are out of luck). You will almost certainly have to inject a VBIOS (`ATY,bin_image` property) that is exactly 64 KBs. Afterwards you will have working external displays. For internal display you most likely will have to inject its EDID (`AAPL00,override-no-connect` property) and set display channel representation to 6 bits (`@0,display-link-component-bits` and `@0,display-pixel-component-bits` properties). If you have a resolution higher than 1600x900 you will likely have to also set `@0,display-dual-link` to 1.
40 | Further details are available in [SSDT sample](./Sample.dsl) to get the general idea.
41 |
42 | - _How could I tune my GPU configuration?_
43 | ATI/AMD GPUs could be configured by `aty_config`, `aty_properties` parameters that one could find in AMDxxxxController.kext Info.plist files. Different framebuffers have overrides for these preferences for lower energy consumption, higher performance, or other reasons. Unfortunately in such combinations they often are unsuitable for different GPUs.
44 | WhateverGreen allows to specify your own preferred parameters via GPU controller properties to achieve best GPU configuration. Use `CFG,` prefix for `aty_config` properties, `PP,` prefix for `aty_properties`, and `CAIL,` prefix for `cail_properties` from AMDRadeonXxxxx.kext Info.plist files. For example, to override `CFG_FB_LIMIT` value in `aty_config` you should use `CFG,CFG_FB_LIMIT` property.
45 | Further details are available in [SSDT sample](./Sample.dsl) to get the general idea.
46 |
47 | - _When do I need to use `radpg` boot argument?_
48 | This argument is as a replacement for the original igork's AMDRadeonX4000.kext Info.plist patch required for HD 7730/7750/7770/R7 250/R7 250X initialisation (`radpg=15`) GPUs to start. WhateverGreen is not compatible with Verde.kext, and it should be deleted. The argument allows to force-enable certain power-gating flags like CAIL_DisableGfxCGPowerGating. The value is a bit mask of CAIL_DisableDrmdmaPowerGating, CAIL_DisableGfxCGPowerGating, CAIL_DisableUVDPowerGating, CAIL_DisableVCEPowerGating, CAIL_DisableDynamicGfxMGPowerGating, CAIL_DisableGmcPowerGating, CAIL_DisableAcpPowerGating, CAIL_DisableSAMUPowerGating. Therefore `radpg=15` activates the first four keys.
49 | Starting with 1.0.3 version you could achieve exactly the same result by manually specifying the necessary properties into your GPU controller (e.g. `CAIL,CAIL_DisableGfxCGPowerGating`). This is better, because it allows you to fine-tune each GPU separately instead of changing these parameters for all the GPUs.
50 |
51 | - _How to change my GPU model?_
52 | The controller kext (e.g. AMD6000Controller) replaces GPU model with a generic name (e.g. AMD Radeon HD 6xxx) if it performs the initialisation on its own. Injecting the properties and disabling this will break connector autodetect, and therefore is quite not recommended. WhateverGreen attempts to automatically detect the GPU model name if it is unspecified. If the autodetected model name is not valid (for example, in case of a fake device-id or a new GPU model) please provide a correct one via `model` property. All the questions about automatic GPU model detection correctness should be addressed to [The PCI ID Repository](http://pci-ids.ucw.cz). In special cases you may submit a [patch](https://github.com/acidanthera/WhateverGreen/pulls) for [kern_model.cpp](../WhateverGreen/kern_model.cpp). GPU model name is absolutely unimportant for GPU functioning.
53 |
54 | - _How should I read EFI driver version?_
55 | This value is by WhateverGreen for debugging reasons. For example, WEAD-102-2017-08-03 stands for WhateverGreen with automatic frame (i.e. RadeonFramebuffer), debug version 1.0.2 compiled on 03.08.2017. Third letter can also be F for fake frame, and B for invalid data. Fourth letter could be R for release builds.
56 |
57 | - _What to do when my GPU does not wake until I start typing on the keyboard?_
58 | If this bothers you, either wait a bit longer or try adding `darkwake=0` boot argument.
59 |
60 | - _How do I know my GPU initialises fine?_
61 | One of the easiest signs is boot time. If initialised improperly, your boot process will stall for 30 extra seconds to get your display ready.
62 |
63 | - _Is it normal to have `Prototype` in OpenGL/OpenCL engine names?_
64 | Yes. It was discovered during the reverse-engineering that the displayed title has no effect on performance. Furthermore, it was discovered that certain attempts to patch this by modifying the identitiers in kexts (e.g. AMDRadeonX4000) may lead to overall system instability. For the improperly coded apps having issues with such naming use `libWhateverName.dylib`.
65 |
66 | - _How do I use my IGPU?_
67 | In most cases IGPU should be used for hardware video decoding (with a connector-less frame). In case you need extra screens, IGPU may be fully enabled. You should not use `-radlogo` boot argument with WhateverGreen.
68 |
69 | - _How do I get hardware video decoding to work?_
70 | Generally hardware video decoding is performed by an IGPU, and thus you are required to inject a connector-less frame. For some GPUs (e.g. HD 7870, HD 6670, HD 7970) it is still possible to get AMD hardware video decoding to work. Please refer to [Shiki's FAQ](./FAQ.Shiki.en.md) for further details. You may need `shikigva=1` on mac models that have forceOfflineRenderer on.
71 |
72 | - _Why would I need to force 24-bit video output?_
73 | Several screens may not support 30-bit video output, but the GPU may not detect this. The result will look as distorted blinking colours. To resolve the issue either buy a more powerful display or add `-rad24` boot argument.
74 |
75 | - _How do I get HDMI audio to work?_
76 | In general it should be enough to rely on AppleALC automatic HDAU correction. It renames the device to HDAU, and injects missing layout-id and hda-gfx (starting with onboard-1) properties. This will not work well with two or more cards of different vendors (e.g. NVIDIA and ATI/AMD), please manually inject the properties in such a case. You may also use `-radnoaudio` boot argument or `no-audio-autofix` GPU controller property to explicitly disable any audio-related property changes.
77 | For identifiers not present in AppleHDAController and AppleHDA you have to add necessary kext patches, see AppleALC [example for 290X](https://github.com/acidanthera/AppleALC/commit/cfb8bef310f31fd330aeb4e10623487a6bceb84d#diff-6246954ac288d4f6dd7eb780c006419d).
78 |
79 | - _My framebuffer amount exceeds connector amount in IOReg (starting with 10.13.2)?_
80 | This is a bug Apple added by fixing another bug of incorrect connector detection from VBIOS. In certain kexts (e.g. AMD9500Controller) they hardcoded 6 connectors as a total connector amount regardless of the number read from VBIOS. The consequences are black screen after wake and/or failure to sleep. To fix this issue you should specify `CFG,CFG_FB_LIMIT` with a correct number, via SSDT for example. Starting with version 1.1.4 this problem is fixed automatically.
81 |
82 | - _Why can a highres DisplayPort-connected display fail to wake (e.g. some LG 4K models)?_
83 | Sometimes AGDC configuration preference could be the case. For 4K and lower it makes sense to try disabling it by passing `CFG,CFG_USE_AGDC` — False (`00`) via SSDT or similar.
84 |
85 | - _How can I configure workload policy?_
86 | Workload policy is a performance optimisation profile used by your GPU. Depending on the workload policy your GPU can consume less power or be more responsive. To configure workload policy specify `PP,PP_WorkLoadPolicyMask` with a corresponding bitmask: `0x01` — DEFAULT_WORKLOAD (default), `0x02` — FULLSCREEN3D_WORKLOAD, `0x04` — POWERSAVING_WORKLOAD, `0x08` — VIDEO_WORKLOAD, `0x10` — VR_WORKLOAD, `0x20` — COMPUTE_WORKLOAD, `0x40` — CUSTOM_WORKLOAD.
87 |
88 | - _How can I force-enable SMU firmware?_
89 | SMU is an IP unit present in some newer GPUs (X5000 series and newer). This unit is responsible for handling select power management tasks and requires a firmware to be loaded by the driver. The firmware is loaded when `ATY,EFIVersion` property is specified with any value (i.e. it is a GPU with Apple-made firmware) or when `Force_Load_FalconSMUFW` property is specified with `kOSBooleanTrue` value (with WEG one can also specify a single byte: `01`).
90 |
91 | - _How to enable the PWM backlight control of the built-in display that is directly wired to AMD Radeon RX 5000 series graphic cards?_
92 | First, you need to add a suitable SSDT-PNLF to enable AppleBacklightDisplay to attach the built-in display. Usually, you need SSDT-PNLF.aml, or SSDT-PNLF-CFL.aml if you are using Coffee Lake and newer. Second, add boot argument `applbkl=3` to enable the PWM backlight control ability of the AMD driver. Then you should be able to adjust the backlight level. Note that this patch is only for the display that is built-in and supports PWM backlight control, and this display is directly wired to the AMD Radeon RX 5000 series graphic cards.
93 |
--------------------------------------------------------------------------------
/Manual/FAQ.Shiki.zh_CN.md:
--------------------------------------------------------------------------------
1 | #### 常见问题:
2 | - _Shiki 在哪里?_
3 |
4 | Shiki 现已成为 [WhateverGreen](https://github.com/acidanthera/WhateverGreen) 的一部分。
5 |
6 | - _我需要 Shiki 吗?_
7 | 如果您有一台 Ivy Bridge 或者更新的平台机器,并且无法使用 iTunes DRM 播放但您的显卡可以在 HDCP 模式下工作的话,您可以尝试使用 Shiki 。
8 | 有时 Shiki 也可以修复 Sandy Bridge 平台的这些问题。
9 | 从 macOS 10.12 开始,在 Ivy Bridge 或更新平台上,没有独立显卡时将无法播放 iTunes 高清视频。
10 |
11 | - _如何禁用 Shiki?_
12 | 请加入 `-shikioff` 启动系统。另外,在使用 -x (安全模式) 或 -s (单用户模式) 启动时 Shiki 也不会载入。
13 |
14 | - _如何打开 Shiki 的排错模式? (需配合 DEBUG 版本 Shiki 使用)_
15 | 请加入 `-shikidbg` 启动系统。
16 |
17 | - _Shiki 能配合什么版本的 OS X/macOS 工作?_
18 | 理论上来说 10.9 或者更新的系统即可,不过,建议在 10.10 或者更新的系统上使用。
19 | 注意: Shiki 需要配合相对新的 iTunes 版本工作。
20 | 如果您在 10.10 或者更新的系统上使用 Shiki 遇到了一些问题,请尝试使用 `-liluslow` 或 `-lilufast` 启动系统。
21 |
22 | - _如何使用 Shiki?_
23 | 建议使用引导器提供的注入 kext 功能来加载 Shiki 。目前已知 Shiki 无法通过 `kextload` 加载;将其安装在 /System/Library/Extensions 或者 /Library/Extensions 也可能会失败。
24 |
25 | - _使用 Shiki 很危险吗?_
26 | 目前 Shiki 比较稳定,不过仍在测试阶段。
27 |
28 | - _Shiki 修改了磁盘上的文件吗?_
29 | 近期版本的 Shiki 不会修改磁盘上的内容,但一些 I/O 指令可能会提示某些文件被修改。(这与一些 API hook 技术有关)
30 |
31 | - _需要修改 SIP (rootless) 配置吗?_
32 | 不,不需要。
33 |
34 | - _在测试 Shiki 之前,如何确定系统已正确配置?_
35 | 您可以查阅[配置列表](https://github.com/acidanthera/WhateverGreen/blob/master/Manual/FAQ.Shiki.zh_CN.md#配置列表),这里面列出了所有的配置要求。
36 |
37 | - _在使用 Shiki 之前,为什么应该正确配置 VDA ?_
38 | 理论上来说这可能不必要,不过这会带来未知的结果。
39 |
40 | - _哪些显卡可能会引发卡顿?_
41 | - 使用 Azul 驱动的显卡 (如 HD 4400, HD 4600) 在没有独立显卡并在使用完整接口的 ig-platform-id 时可能因为不工作的 HDCP 而无法播放高清视频,但这不是 Shiki 导致的,您需要 [WhateverGreen](https://github.com/acidanthera/WhateverGreen) 来解决这个问题。
42 |
43 | - _我的机器会被禁止吗?_
44 | 如果您可以播放一个电影的预告片,但购买后的电影无法播放,即使已经对此电脑进行了授权,那么您的 NIC MAC 可能已被禁止。有时可以通过注销账户,并稍等片刻来重新授权来解决,但如果这无效的话,您可能需要修改以太网 MAC 地址。
45 | 查阅[系统配置常见问题](https://github.com/acidanthera/WhateverGreen/blob/master/Manual/FAQ.Shiki.zh_CN.md#系统配置常见问题)以获取 libHookMac 的详细用法,如果它可以工作的话,尝试修改您的以太网卡 MAC 地址。(或使用其他方式修改亦可)
46 |
47 | - _Shiki 开源吗?_
48 | 从 2.0.0 版本起开源。
49 |
50 | - _如何下载一个受 DRM 保护的视频来测试 Shiki 是否正常工作?_
51 | 首先请在 终端 输入: `defaults write com.apple.coremedia cfbyteflume_trace 1`
52 | 然后在 控制台 中 过滤 栏中输入 iTunes ,您会看到一个影片预告片的地址,像下面这样:
53 | `... <<< CFByteFlume >>> FigCFHTTPCheckCacheValidator: Comparing dictUrl = http://.....m4v, url = http://......m4v`
54 | 粘贴到浏览器中,即可下载此影片。
55 | 或者,这里有一个例子,您可以直接下载[此影片](https://drive.google.com/file/d/12pQ5FFpdHdGOVV6jvbqEq2wmkpMKxsOF/view)。
56 |
57 | - _为什么 DRM 播放一段时间后开始出现一些错乱?_
58 | 从测试中来看这似乎是 Apple DRM 解码器的问题,并且在某些白苹果上也存在。
59 | 基本上这样的问题不会出现,除了在某些 1080p 高比特率的视频上,如遇到这样的问题,请尝试重新启动电脑,重设 DRM 配置(查阅[系统配置常见问题](https://github.com/acidanthera/WhateverGreen/blob/master/Manual/FAQ.Shiki.zh_CN.md#系统配置常见问题)),检查电源管理是否正常工作。
60 |
61 | - _可以用 Shiki 播放 HTML5 Netfilx 视频吗?_
62 | 不,Netflix 限制了 1080p 的某些视频,只有极少数的机型才可以播放。
63 |
64 | - _可以用 Shiki 修改其他系统运行库吗?_
65 | 可以,这是完全可能的。
66 |
67 | #### 系统配置常见问题:
68 | - _如何确定硬件解码可用?_
69 | 运行 [VDADecoderChecker for 10.11](https://i.applelife.ru/2019/05/451892_10.11_VDADecoderChecker.zip)/[VDADecoderChecker for 10.12+](https://i.applelife.ru/2019/05/451893_10.12_VDADecoderChecker.zip) ([或者自行编译](https://github.com/cylonbrain/VDADecoderCheck)) 然后查阅它的输出:
70 | `GVA info: Successfully connected to the Intel plugin, offline Gen75`
71 | `Hardware acceleration is fully supported`
72 |
73 | - _我如何确定 IMEI/IGPU 存在于 IOReg 中?_
74 | 终端 中执行 `ioreg | grep IMEI` ,确保存在像这样的输出:
75 | ` | | +-o IMEI@16 `
76 |
77 | - _如何确认当前的 ig-platform-id?_
78 | 终端 中执行 `ioreg -l | grep platform-id` ,确保存在像这样的输出:
79 | ` | | | | "AAPL,ig-platform-id" = <04001204>`
80 | `04 00 12 04` 即为当前的 ig-platform-id 。
81 |
82 | - _如何启用 AppleGVA 排错模式?_
83 | 终端 中执行:
84 | `defaults write com.apple.AppleGVA gvaDebug -boolean yes`
85 | `defaults write com.apple.AppleGVA enableSyslog -boolean yes`
86 |
87 | - _如何启用 FP 排错模式?_
88 | 终端 中执行:
89 | `defaults write com.apple.coremedia fp_trace 2`
90 |
91 | - _如何设置硬件解码器偏好设置 (一些 AMD/ATI 显卡和较老的 NVIDIA 可能需要)?_
92 | 终端 中执行下面的命令***之一***:
93 | `defaults write com.apple.AppleGVA forceNV -boolean yes` — 启用 NVIDIA 解码器
94 | `defaults write com.apple.AppleGVA forceATI -boolean yes` — 启用 ATI 解码器
95 | `defaults write com.apple.AppleGVA forceIntel -boolean yes` — 启用 Intel 解码器
96 | `defaults write com.apple.AppleGVA forceSWDecoder -boolean yes` — 启用 software 解码器
97 | `defaults write com.apple.coremedia hardwareVideoDecoder disable` — 禁用 硬件 解码器
98 | `defaults write com.apple.coremedia hardwareVideoDecoder force` — 启用 硬件 解码器
99 | 注: 多数情况下这些是不需要的,错误的设定可能会导致 CL、VDA 解码不正常。
100 |
101 | - _如何重设 DRM 配置 (用于修复闪退、崩溃等问题)?_
102 | 终端 中执行下面的命令:
103 | `defaults delete com.apple.coremedia`
104 | `defaults delete com.apple.AppleGVA`
105 | `sudo rm -rf /Users/Shared/SC\ Info`
106 | `sudo defaults delete com.apple.coremedia`
107 | `sudo defaults delete com.apple.AppleGVA`
108 | 在这之后确保以下命令不会输出任何内容 (表明 AppleGVA 已正确签名):
109 | `codesign --no-strict --verify /System/Library/PrivateFrameworks/AppleGVA.framework`
110 | 如果以上命令输出了内容,尝试恢复原版的 AppleGVA.framework ,并正确设置权限。
111 | 重新启动两次。
112 |
113 | - _如何通过 [HookMac](https://github.com/acidanthera/WhateverGreen/tree/master/Tools/HookMac) 修改 NIC MAC 地址?_
114 | - 禁用 SIP (System Integrity Protection);
115 | - 终端 中执行以下命令 (请自行替换 libHookMac.dylib 的完整路径以及新的 MAC 地址):
116 | `DYLD_INSERT_LIBRARIES=/full/path/to/libHookMac.dylib MAC=00:11:22:33:44:55 /Applications/iTunes.app/Contents/MacOS/iTunes`;
117 | - 您将会看到对应的输出,如果成功的话。
118 |
119 | - _如何确认 共享缓存 可用?_
120 | 终端 中执行以下两段命令,并比较它们的输出:
121 | `DYLD_PREBIND_DEBUG=1 DYLD_SHARED_CACHE_DONT_VALIDATE=1 "/Applications/QuickTime Player.app/Contents/MacOS/QuickTime Player"`
122 | `DYLD_PREBIND_DEBUG=1 "/Applications/QuickTime Player.app/Contents/MacOS/QuickTime Player"`
123 | 如果两者差异很大,并且第二段命令输出了很多路径,则表明 共享缓存 已损坏。
124 | 若 共享缓存 已损坏,请禁用 Shiki (通过 `-Shikioff` 启动),并在 终端 中运行: `sudo update_dyld_shared_cache -force`
125 |
126 | - _哪些机型支持硬件加速?_
127 | 请查阅 `/System/Library/PrivateFrameworks/AppleGVA.framework/Info.plist`, 如果您看到了您的机型, 则表明这个机型支持硬件解码加速。 您应该选择一个与您机器配备最接近的型号。 比如, iMac13,1 配备一个核芯显卡和一个独立显卡,然而 iMac13,3 只有一个核芯显卡。如果您使用的机型使用独立显卡,但没有核芯显卡,VDA 将不会工作,并且您可能会从 VDADecoderChecker 看到错误信息。欲修正此错误,您可以选择一个正确的机型,或是修改 Info.plist 中的 `forceOfflineRenderer` 项,它需要被设为 `NO` 。
128 |
129 | - _如何启用 Intel 在线解码器如果 AppleGVA 强制将其设置为离线模式?_
130 | 请加入 `shikigva=1` 到 `boot-args` 或者任何 `GPU` 的 `DeviceProperties` 下启动系统。
131 |
132 | - _如何只为 Music, Safari 以及 TV 启用 AMD DRM,并且对其他应用仅使用 `IGPU`?_
133 | 请加入 `shikigva=80` 到 `boot-args` 或者任何 `GPU` 的 `DeviceProperties` 下启动系统。如果此方法引起了冻屏(注意:Apple 官方已在 10.15.4+ 部分修正此问题),则使用
134 | `shikigva=16`。
135 | 注意:在不同配置的机器上,并非所有 DRM 种类均可用。请查阅 [此处](https://applelife.ru/posts/846582) 以获取详细信息。
136 |
137 | - _如何在 `MacPro5,1` 上使用 `QuickTime` 配合 `Apple TV+` 播放 `iTunes` 已购买视频?_
138 | 使用以下两种方法之一:
139 | 使用 `OpenCore` 伪装成 `iMacPro1,1` (推荐)
140 | 不使用 `Opencore` 并配合参数 `shikigva=160 shiki-id=Mac-7BA5B2D9E42DDD94`
141 |
142 | - _如何为某些 NVIDIA 显卡注入 IOVARendererID/IOVARendererSubID 属性?_
143 | NVIDIA 显卡驱动没有正确加入这些对 Maxwell / Pascal 架构显卡来说必要的用于 VDA 解码的键值,您可以通过一个 Info 空壳来加入它们。以下是正确的值:
144 | IOVARendererID → `<08 00 04 01>`
145 | IOVARendererSubID → `<03 00 00 00>`
146 | VP3 需要一个不同的 IOVARendererID → `<04 00 04 01>`.
147 | 感谢 igork 的发现。
148 | 或者,亦可使用 [WhateverGreen](https://github.com/acidanthera/WhateverGreen) (需使用 1.2.0 或更高版本) 来自动设定这些值。
149 |
150 | - _有关「不受原生支持」的配置的相关情况 (NVIDIA + SNB/SKL/KBL 和 AMD + IVY)_: [WhateverGreen](https://github.com/acidanthera/WhateverGreen) 有助于改善在某些应用程序下的情况,macOS 10.13.4 起此问题已解决。
151 |
152 | - _如果 AMD 显卡无法使用 VDA 解码器_
153 | 使用 Intel 核芯显卡作为主显卡,并注入一个所有 connectors 都可用的 ig-platform-id (如 HD 4000 使用 `<03 00 66 01>`;HD 4600 使用 `<03 00 22 0D>`),这似乎改善了某些 AMD 显卡的情况。(如 HD 7750)
154 |
155 | - _如果启用 ATI 解码器后,AMD 显卡已成功启用硬件加速解码,但 DRM 解码仍不工作_
156 | 某些 AMD 显卡如 HD 7750,支持硬件加速解码,但无法解码 DRM 视频。原因不明,请正常使用 Shiki 。
157 |
158 | - _[BoardHash](https://github.com/acidanthera/WhateverGreen/tree/master/Tools/BoardHash) 是做什么的?_
159 | BoardHash 可以用来生成 board-id 的哈希值,类似于 CoreAUC.framework 中的 `_PsZXJ2EK7ifxrtgc` 函数。
160 | 比如, Mac-F221BEC8 (MacPro5,1) 对应 5f571162ce99350785007863627a096bfa11c81b.
161 | 目前已知 MacPro5,1 可以无视解码器状态而直接允许 HD 4000 播放高清视频。
162 |
163 | - _如何为 HD 4400, HD 4600 以及 HD 530 禁用 PAVP/HDCP ?_
164 | 考虑使用 [WhateverGreen](https://github.com/acidanthera/WhateverGreen) 以禁用 PAVP/HDCP 来避免冻屏。
165 |
166 | #### 配置列表
167 |
168 | - _如果您拥有以下配置,Shiki 是不需要的:_
169 | - 可用的 DRM VDA AMD 显卡 (如 HD 7870, HD 6670 和 HD 7970);
170 | - 可用的 DRM VDA NVIDIA 显卡 (可能 2xx 系列以及一些其他的型号).
171 |
172 | 这些配置不确定具体情况,不过据一些朋友反馈可能不需要 Shiki :
173 | - 已启用核芯显卡并且为主显卡,并且 ig-platform-id 包含所有 connectors (如 `<03 00 66 01>`),或者完全移除/禁用,IOReg 中没有相关痕迹 (如通过 [D2EN register](https://applelife.ru/threads/chernye-trejlery-itunes.42290/page-14#post-584519));
174 | - 硬件视频解码器偏好设置被设定为 ATI/NVIDIA (取决于具体安装的显卡);
175 | - VDADecoderChecker 确认 VDA 解码器在 VP3 (NVIDIA) 或者 AMD 解码器可用;
176 | - 机型为一个支持硬件加速的型号
177 |
178 | - _适用于无冻屏的 Intel 显卡或者任何独立显卡的情况:_
179 | - 已启用核芯显卡, 并且 ig-platform-id 不包含所有 connectors (如 `<04 00 12 04>`, `<07 00 62 01>`), 在只有核芯显卡的情况下使用全部 connectors 的 FrameBuffer;
180 | - 正确配置的独立显卡,并且 IOReg 中存在 IOVARendererID 属性;
181 | - VDADecoderChecker 确认 Intel 离线 (在线) VDA 解码器正常工作;
182 | - IOReg 中存在 IMEI 设备;
183 | - 无覆盖的偏好设置使用;
184 | - 机型为一个支持硬件加速的型号
185 |
186 | - _适用于 HD4400, HD4600 无独立显卡的情况:_
187 | - 已启用核芯显卡,并且 ig-platform-id 包含所有 connectors (如 `<03 00 22 0d>`, `<00 00 16 0a>`)。将 IGPU 重命名为 GFX0 或任意其他名称可能会降低冻屏出现的可能;
188 | - 显卡驱动/FrameBuffer 已禁用 PAVP/HDCP;
189 | - 硬件视频解码器已通过 defaults 指令禁用 (否则视频在唤醒后将无法播放);
190 | - IOReg 中存在 IMEI 设备;
191 | - 机型为一个支持硬件加速的型号
192 |
193 | - _适用于不受原生支持的 CPU (如 Haswell Celeron E):_
194 | 硬件视频加速解码不会在这些 CPU 上工作,以及您需要 FakeCPUID 来启动。
195 | 完全禁用核芯显卡,或者将其重命名为其他的名字 (如 IGFX),安装 Shiki 。
196 | 目前不确定需要哪些偏好设置,不过已知通过修改 AppleGVA 中的 plist 或使用 MacPro5,1 机型有时或许可以播放高清视频。
197 |
198 |
199 | _感谢: 07151129, Andrey1970, Сашко666, chrome, family1232009, garcon, iDark Soul, igork, lvs1974, m-dudarev, Mieze, Quadie, savvas, tatur_sn, 以及一些其他帮助开发 Shiki 的朋友。_
200 |
201 | 译者: [PMheart](https://github.com/PMheart)
202 |
--------------------------------------------------------------------------------
/Manual/Img/Clover1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/Clover1.png
--------------------------------------------------------------------------------
/Manual/Img/Clover2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/Clover2.png
--------------------------------------------------------------------------------
/Manual/Img/WhiskeyLake.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/WhiskeyLake.png
--------------------------------------------------------------------------------
/Manual/Img/basic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/basic.png
--------------------------------------------------------------------------------
/Manual/Img/bin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/bin.png
--------------------------------------------------------------------------------
/Manual/Img/bios.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/bios.png
--------------------------------------------------------------------------------
/Manual/Img/cfl-r_igpu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/cfl-r_igpu.png
--------------------------------------------------------------------------------
/Manual/Img/connector.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/connector.png
--------------------------------------------------------------------------------
/Manual/Img/dGPU_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/dGPU_off.png
--------------------------------------------------------------------------------
/Manual/Img/dpcd_mlr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/dpcd_mlr.png
--------------------------------------------------------------------------------
/Manual/Img/dvmt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/dvmt.png
--------------------------------------------------------------------------------
/Manual/Img/edid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/edid.png
--------------------------------------------------------------------------------
/Manual/Img/hdmi20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/hdmi20.png
--------------------------------------------------------------------------------
/Manual/Img/hsw_igpu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/hsw_igpu.png
--------------------------------------------------------------------------------
/Manual/Img/ifbt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/ifbt.png
--------------------------------------------------------------------------------
/Manual/Img/ivy_imei.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/ivy_imei.png
--------------------------------------------------------------------------------
/Manual/Img/kbl-r_igpu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/kbl-r_igpu.png
--------------------------------------------------------------------------------
/Manual/Img/kbl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/kbl.png
--------------------------------------------------------------------------------
/Manual/Img/lspcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/lspcon.png
--------------------------------------------------------------------------------
/Manual/Img/lspcon_debug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/lspcon_debug.png
--------------------------------------------------------------------------------
/Manual/Img/max-pixel-clock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/max-pixel-clock.png
--------------------------------------------------------------------------------
/Manual/Img/sem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/sem.png
--------------------------------------------------------------------------------
/Manual/Img/snb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/snb.png
--------------------------------------------------------------------------------
/Manual/Img/snb_igpu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/snb_igpu.png
--------------------------------------------------------------------------------
/Manual/Img/snb_imei.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/snb_imei.png
--------------------------------------------------------------------------------
/Manual/Img/vda.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/vda.png
--------------------------------------------------------------------------------
/Manual/Img/vda2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Manual/Img/vda2.png
--------------------------------------------------------------------------------
/Manual/NVCAP.bt:
--------------------------------------------------------------------------------
1 | LittleEndian();
2 |
3 | typedef unsigned char UINT8;
4 | typedef unsigned short UINT16;
5 |
6 | #define NV_NVCAP_VERSION_LEGACY 4
7 | /* Starting from 8000-series */
8 | #define NV_NVCAP_VERSION_MODERN 5
9 |
10 | struct NV_NVCAP {
11 | UINT8 Version; /* NV_NVCAP_VERSION_MODERN */
12 | UINT8 IsMobile; /* 1 for mobiles */
13 | UINT8 Composite; /* S-Video */
14 | UINT8 field_3; /* Backlight-related? */
15 | /**
16 | https://download.nvidia.com/open-gpu-doc/DCB/2/DCB-4.x-Specification.html
17 |
18 | There are N independent display paths in NVIDIA. They are called heads.
19 | For older cards there are up to 2. For newer cards there are up to 4.
20 | One can view each head as a video output source, which is connected to
21 | one or more DCB entries (as explained by the specification).
22 | These DCB entries map to physical ports on the GPU. There is a finite
23 | number of DCB entries in the GPU, which can be at most 16 * head count,
24 | i.e. 32 for 2-head GPUs. In reality it is usually much less, like 4-5.
25 |
26 | NVCAP contains indices of DCB entries per head in a mask format, which
27 | must match the actual mapping present in the VBIOS. While it should be
28 | reconfigurable, I do not think older macOS drivers can do that.
29 |
30 | For example, setting Head0DCBMask to 0x3 and Head1DCBMask to 0xC means
31 | that DCB entries 0 and 1 are routed through head 0 and DCB entries 2 and 3
32 | are routed through head 1. This means that first two DCB entries will
33 | have Head = 1 in the VBIOS, and second two will have Head = 2 (see the spec).
34 |
35 | Since DCB entries are sorted by boot priority, LVDS is usually DCB entry 0
36 | and is connected exclusively to head 0. Composite (TVDCBMask), when available,
37 | is usually 16, i.e. DCB entry 5.
38 | **/
39 | UINT16 TVDCBMask;
40 | UINT16 Head0DCBMask;
41 | UINT16 Head1DCBMask;
42 | /* GPUs before GK107 only support two heads, thus Head2DCBMask and Head3DCBMask are 0. */
43 | UINT16 Head2DCBMask;
44 | UINT16 Head3DCBMask;
45 | UINT8 ScriptBasedPowerAndBacklight;
46 | UINT8 field_f; /* Hardcoded to 0xF on newer models or 0x7 on older */
47 | UINT8 field_10; /* EDID_Manufacturer_Reserved_Timings, 10bit support? */
48 | UINT8 field_11;
49 | UINT8 field_12;
50 | UINT8 field_13;
51 | };
52 |
53 | NV_NVCAP NvCap;
54 |
--------------------------------------------------------------------------------
/Manual/Sample.dsl:
--------------------------------------------------------------------------------
1 | DefinitionBlock ("", "SSDT", 2, "ACDT", "AMDGPU", 0x00001000)
2 | {
3 | External (_SB_.PCI0, DeviceObj)
4 | External (_SB_.PCI0.GFX0, DeviceObj)
5 | External (_SB_.PCI0.PEG0, DeviceObj)
6 | External (_SB_.PCI0.PEG0.PEGP, DeviceObj)
7 |
8 | Scope (\_SB.PCI0)
9 | {
10 | // Follow your motherboard structure regarding the scope hierarchy. This example contains:
11 | // PEG0 -> PEGP (GPU #1) and HDAU (HDMI audio for GPU #1)
12 | // PEG1 -> PEGP (GPU #2) not installed
13 | // PEG2 -> PEGP (GPU #3) not installed
14 | // PEG3 -> PEGP (GPU #4) not installed
15 | // IMEI (Intel IMEI device required for proper hardware video decoding functioning)
16 | // GFX0 (disabled original IGPU name)
17 | // IGPU (Intel GPU with a connector-less frame used for hardware video decoding)
18 | //
19 | // Depending on your method you may rename PEGP to GFX0.
20 | Scope (PEG0)
21 | {
22 | Scope (PEGP)
23 | {
24 | Method (_DSM, 4, NotSerialized) // _DSM: Device-Specific Method
25 | {
26 | Store (Package ()
27 | {
28 | // Write the preferred GPU index here (1-4)
29 | "AAPL,slot-name",
30 | Buffer ()
31 | {
32 | "Slot-1"
33 | },
34 |
35 | // Write the main main monitor index (currently 0) here, the value does not matter
36 | "@0,AAPL,boot-display",
37 | Buffer (Zero) {}
38 |
39 | /*
40 |
41 | // Only use this if your GPU device identifier is not natively supported in macOS kexts
42 | "device-id",
43 | Buffer (0x04)
44 | {
45 | 0x12, 0x34, 0x00, 0x00
46 | },
47 |
48 | // Only use this if automatic detection fails or you are faking your GPU device-id
49 | "model",
50 | Buffer ()
51 | {
52 | "AMD Radeon HD 6450"
53 | },
54 |
55 | // Only use this if you are not satisfied with automatic HDMI injection
56 | // Make sure not to write the same onboard index for each installed GPU
57 | "hda-gfx",
58 | Buffer ()
59 | {
60 | "onboard-1"
61 | },
62 |
63 | // Only use this if you need special connectors that are incompatible with the automatic connector detection
64 | "connectors",
65 | Buffer ()
66 | {
67 | 0x00, 0x04, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x12, 0x04, 0x04, 0x01,
68 | 0x00, 0x08, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x22, 0x05, 0x01, 0x03,
69 | 0x04, 0x00, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x10, 0x00, 0x05, 0x06,
70 | 0x04, 0x00, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x11, 0x02, 0x06, 0x05
71 | },
72 |
73 | // You may only specify this with connectors property when the amount of connectors differs from autodetected
74 | "connector-count",
75 | Buffer ()
76 | {
77 | 0x04, 0x00, 0x00, 0x00
78 | },
79 |
80 | // Only use this with automatic connector detection when you need manual priority.
81 | // Each value is a sense id to get a higher priority.
82 | // Automatic ordering is done by type: LVDS, DVI, HDMI, DP, VGA.
83 | // You may leave this empty to order all the connectors by type.
84 | // Assume autodetected connectors: 0x03 DP, 0x02 DVI_D, 0x06 HDMI, 0x05 DVI_D, 0x04 VGA
85 | // With the value pri will become: 0x0005 , 0x0001 , 0x0004 , 0x0003 , 0x0002
86 | "connector-priority",
87 | Buffer ()
88 | {
89 | 0x02, 0x04
90 | },
91 |
92 | // The properties below allow you to configure aty_config, aty_properties, cail_properties
93 |
94 | // This will change CAIL_DisableDrmdmaPowerGating in cail_properties to false
95 | // Note: buffer of 1 byte long with 0x01 / 0x00 values is transormed into boolean
96 | "CAIL,CAIL_DisableDrmdmaPowerGating",
97 | Buffer ()
98 | {
99 | 0x01
100 | },
101 |
102 | // This will change CFG_FB_LIMIT in aty_config to 6
103 | // Starting with 10.13.2 AAPL hardcodes framebuffer limit in certain kexts.
104 | // In particular, for AMD9500Controller the value is 6.
105 | // This is not correct for some GPUs (e.g. Radeon Pro, which has 3), so you are to specify
106 | // the correct value right here.
107 | "CFG,CFG_FB_LIMIT",
108 | 0x06,
109 |
110 | // This will change HELLO_WORLD in aty_properties to <01 02 03 04>
111 | "PP,HELLO_WORLD",
112 | Buffer ()
113 | {
114 | 0x01, 0x02, 0x03, 0x04
115 | }
116 |
117 | // The properties below are usually relevant to mobile ATI/AMD GPUs
118 |
119 | // Most mobile GPUs fail to provide their VBIOS
120 | // Dump it and inject it here.
121 | // You must cut or pad it by 64 KB (GOP is not relevant).
122 | "ATY,bin_image",
123 | Buffer (0x00010000)
124 | {
125 | // Put your VBIOS here (you could extract it with Linux or Windows)
126 | },
127 |
128 | // Works as AAPL%02X,override-no-connect, where %02X is display index e.g. 00
129 | "AAPL00,override-no-connect",
130 | Buffer (0x80)
131 | {
132 | // Put your EDID here (you could extract it with Linux or Windows)
133 | // Note that in some cases the extracted EDID may not be compatible and
134 | // as a result you may see visual glitches.
135 | // After you got at least something to show you could use edid-fix.sh script
136 | // (based on pokenguyen's work) to generate a compatible EDID.
137 | },
138 |
139 | // Just like AAPL00, @0 represents your display index (from the connectors).
140 | // From there on only @X notation could be used for displays other than 0.
141 | // I.e. AAPL01,override-no-connect is OK but AAPL01,DualLink is NOT.
142 |
143 | // Equal to AAPL00,DualLink, only supported for LVDS displays.
144 | // Required bandwidth speed is calculated as follows:
145 | // BITS_PER_PIXEL * WIDTH * HEIGHT * FREQUENCY / (1024 * 1024) = N Mbps/s
146 | // It depends on hardware but you could commonly assume 800 Mbit/s per link
147 | // If calculated N is above this value, you may require the property below.
148 | "@0,display-dual-link",
149 | Buffer ()
150 | {
151 | 0x01, 0x00, 0x00, 0x00
152 | },
153 |
154 | // Equal to AAPL00,LinkFormat = 0 (0 - 6 bits, 1 - 8 bits)
155 | // Most laptop displays do not support 24-bit (32) colour but only 18-bit.
156 | // This property must be used if you see "gradient" glitches.
157 | "@0,display-link-component-bits",
158 | Buffer () {
159 | 0x06, 0x00, 0x00, 0x00
160 | },
161 |
162 | // Equal to AAPL00,PixelFormat = 0 (0 - 6 bits, 1 - 8 bits)
163 | // Similar to display-link-component-bits
164 | "@0,display-pixel-component-bits",
165 | Buffer ()
166 | {
167 | 0x06, 0x00, 0x00, 0x00
168 | },
169 |
170 | // Equal to AAPL00,Dither
171 | // In general you should avoid this property, since it most likely will decrease
172 | // visual quality. However, on some displays you may get slightly better picture
173 | // with this property set to 1.
174 | "@0,display-dither-support",
175 | Buffer ()
176 | {
177 | 0x01, 0x00, 0x00, 0x00
178 | }
179 |
180 | */
181 | }, Local0)
182 | DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))
183 | Return (Local0)
184 | }
185 | }
186 |
187 | /*
188 |
189 | // Only use this if you are not satisfied with automatic HDMI injection
190 | Device (HDAU)
191 | {
192 | Name (_ADR, One) // _ADR: Address
193 | Method (_DSM, 4, NotSerialized) // _DSM: Device-Specific Method
194 | {
195 | If (LEqual (Arg2, Zero))
196 | {
197 | Return (Buffer (One)
198 | {
199 | 0x03
200 | })
201 | }
202 |
203 | Return (Package ()
204 | {
205 | // layout-id should be defined, though the value is unused
206 |
207 | "layout-id",
208 | Buffer (0x04)
209 | {
210 | 0x01, 0x00, 0x00, 0x00
211 | },
212 |
213 | "hda-gfx",
214 | Buffer ()
215 | {
216 | "onboard-1"
217 | }
218 | })
219 | }
220 | }
221 |
222 | */
223 | }
224 |
225 | // Below goes an example for IGPU injection useful for enabling hardware video decoding and other stuff.
226 |
227 | Device (IMEI)
228 | {
229 | Name (_ADR, 0x00160000) // _ADR: Address
230 | }
231 |
232 | Scope (GFX0)
233 | {
234 | Name (_STA, Zero) // _STA: Status
235 | }
236 |
237 | Device (IGPU)
238 | {
239 | Name (_ADR, 0x00020000) // _ADR: Address
240 | Method (_DSM, 4, NotSerialized) // _DSM: Device-Specific Method
241 | {
242 | Store (Package ()
243 | {
244 | "name",
245 | Buffer ()
246 | {
247 | "display"
248 | },
249 |
250 | // This is a connector-less frame for Azul HD 4600
251 |
252 | "AAPL,ig-platform-id",
253 | Buffer (0x04)
254 | {
255 | 0x04, 0x00, 0x12, 0x04
256 | },
257 |
258 | // This is an override for built-in device-id
259 |
260 | "device-id",
261 | Buffer (0x04)
262 | {
263 | 0x12, 0x04, 0x00, 0x00
264 | }
265 | }, Local0)
266 | DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))
267 | Return (Local0)
268 | }
269 | }
270 |
271 | Method (DTGP, 5, NotSerialized)
272 | {
273 | If (LEqual (Arg0, ToUUID ("a0b5b7c6-1318-441c-b0c9-fe695eaf949b")))
274 | {
275 | If (LEqual (Arg1, One))
276 | {
277 | If (LEqual (Arg2, Zero))
278 | {
279 | Store (Buffer (One)
280 | {
281 | 0x03
282 | }, Arg4)
283 | Return (One)
284 | }
285 |
286 | If (LEqual (Arg2, One))
287 | {
288 | Return (One)
289 | }
290 | }
291 | }
292 |
293 | Store (Buffer (One)
294 | {
295 | 0x00
296 | }, Arg4)
297 | Return (Zero)
298 | }
299 | }
300 | }
301 |
--------------------------------------------------------------------------------
/Manual/edid-gen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # This code is based off HP ProBook 4x30s Fix EDID by pokenguyen
3 |
4 | GenEDID() {
5 | /usr/libexec/PlistBuddy -c "Print :$1" /tmp/display.plist &>/dev/null || return 0
6 |
7 | rm -f /tmp/EDID.bin
8 |
9 | EDID=$(/usr/libexec/PlistBuddy -x -c "Print :$1" /tmp/display.plist |
10 | tr -d '\n\t' | grep -o 'IODisplayEDID[^<]*' |
11 | sed 's/.*IODisplayEDID<\/key>//' | base64 -D | xxd -p | tr -d '\n\t\s')
12 | version=${EDID:38:2}
13 | basicparams=${EDID:40:2}
14 | checksum=${EDID:254:2}
15 |
16 | newchecksum=$(printf '%x' $((0x$checksum + 0x$version + 0x$basicparams - 0x04 - 0x90)) | tail -c 2)
17 | newedid=${EDID:0:38}0490${EDID:42:212}${newchecksum}
18 |
19 | echo $newedid | xxd -r -p >>/tmp/EDID.bin
20 |
21 | if [ $? -eq 0 ]; then
22 | RegName=$(/usr/libexec/PlistBuddy -c "Print :$1:IORegistryEntryName" /tmp/display.plist)
23 | DisplayFlags=$(/usr/libexec/PlistBuddy -c "Print :$1:IODisplayConnectFlags" /tmp/display.plist)
24 | VenID=$(/usr/libexec/PlistBuddy -c "Print :$1:DisplayVendorID" /tmp/display.plist)
25 | VenIDhex=$(printf '%x\n' $VenID)
26 | ProdID=$(/usr/libexec/PlistBuddy -c "Print :$1:DisplayProductID" /tmp/display.plist)
27 | ProdIDhex=$(printf '%x\n' $ProdID)
28 | GenPlist=~/"Desktop/${VenIDhex}_${ProdIDhex}.plist"
29 | GenBin=~/"Desktop/${VenIDhex}_${ProdIDhex}.bin"
30 |
31 | rm -f "$GenPlist" "$GenBin"
32 |
33 | # This check does not really detect external displays
34 | if [ "$RegName" == "AppleBacklightDisplay" -o "$DisplayFlags" == "$(echo AAgAAA== | base64 -D)" ] ||
35 | [ "$RegName" == "AppleDisplay" -o "$DisplayFlags" == "$(echo AAgAAA== | base64 -D)" ]; then
36 |
37 | /usr/libexec/PlistBuddy -c "Add :DisplayProductName string 'Display'" "$GenPlist"
38 | /usr/libexec/PlistBuddy -c "Add :test array" "$GenPlist"
39 | /usr/libexec/PlistBuddy -c "Merge /tmp/display.plist :test" "$GenPlist"
40 | /usr/libexec/PlistBuddy -c "Copy :test:$1:DisplayProductID :DisplayProductID" "$GenPlist"
41 | /usr/libexec/PlistBuddy -c "Copy :test:$1:DisplayVendorID :DisplayVendorID" "$GenPlist"
42 |
43 | /usr/libexec/PlistBuddy -c "Remove :test" "$GenPlist"
44 | /usr/libexec/PlistBuddy -c "Import :IODisplayEDID /tmp/EDID.bin" "$GenPlist"
45 |
46 | mv /tmp/EDID.bin "$GenBin"
47 |
48 | echo "Display $1"
49 | echo " vendor id ${VenIDhex}"
50 | echo " product id ${ProdIDhex}"
51 | echo "EDID:"
52 | xxd -i "$GenBin" | grep -vE 'unsigned|}'
53 |
54 | echo "If you cannot inject this EDID via SSDT (AAPL00,override-no-connect), save $GenPlist as:"
55 | echo "/System/Library/Displays/Contents/Resources/Overrides/DisplayVendorID-${VenIDhex}/DisplayProductID-${ProdIDhex}.plist"
56 | else
57 | echo "External display detected (${VenIDhex}_${ProdIDhex}}!"
58 | fi
59 | else
60 | echo "No display detected!"
61 | fi
62 | }
63 |
64 | rm -f /tmp/display.plist
65 |
66 | case $(ioreg -n AppleBacklightDisplay -rxw0) in
67 | "")
68 | ioreg -n AppleDisplay -arxw0 >/tmp/display.plist
69 | ;;
70 | *)
71 | ioreg -n AppleBacklightDisplay -arxw0 >/tmp/display.plist
72 | ;;
73 | esac
74 |
75 | GenEDID 0 && GenEDID 1 && GenEDID 2
76 | rm -f /tmp/display.plist /tmp/EDID.bin
77 |
--------------------------------------------------------------------------------
/Manual/reference.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // reference.cpp
3 | // WhateverGreen
4 | // Explanation of how RadeonFramebuffer connectors are created
5 | // Reverse-engineered from AMDSupport.kext
6 | //
7 | // Copyright © 2017 vit9696. All rights reserved.
8 | //
9 |
10 | /**
11 | * Connectors from AMDSupport since 10.12
12 | */
13 | struct ModernConnector {
14 | uint32_t type;
15 | uint32_t flags;
16 | uint16_t features;
17 | uint16_t priority;
18 | uint32_t reserved1;
19 | uint8_t transmitter;
20 | uint8_t encoder;
21 | uint8_t hotplug;
22 | uint8_t sense;
23 | uint32_t reserved2;
24 | };
25 |
26 | enum ConnectorType {
27 | ConnectorLVDS = 0x2,
28 | ConnectorDigitalDVI = 0x4,
29 | ConnectorSVID = 0x8,
30 | ConnectorVGA = 0x10,
31 | ConnectorDP = 0x400,
32 | ConnectorHDMI = 0x800,
33 | ConnectorAnalogDVI = 0x2000
34 | };
35 |
36 | /**
37 | * Internal atom connector struct since 10.13
38 | */
39 | struct AtomConnectorInfo {
40 | uint16_t *atomObject;
41 | uint16_t usConnObjectId;
42 | uint16_t usGraphicObjIds;
43 | uint8_t *hpdRecord;
44 | uint8_t *i2cRecord;
45 | };
46 |
47 | // Definitions taken from asic_reg/ObjectID.h
48 | enum {
49 | /* External Third Party Encoders */
50 | ENCODER_OBJECT_ID_SI170B = 0x08,
51 | ENCODER_OBJECT_ID_CH7303 = 0x09,
52 | ENCODER_OBJECT_ID_CH7301 = 0x0A,
53 | ENCODER_OBJECT_ID_INTERNAL_DVO1 = 0x0B, /* This belongs to Radeon Class Display Hardware */
54 | ENCODER_OBJECT_ID_EXTERNAL_SDVOA = 0x0C,
55 | ENCODER_OBJECT_ID_EXTERNAL_SDVOB = 0x0D,
56 | ENCODER_OBJECT_ID_TITFP513 = 0x0E,
57 | ENCODER_OBJECT_ID_INTERNAL_LVTM1 = 0x0F, /* not used for Radeon */
58 | ENCODER_OBJECT_ID_VT1623 = 0x10,
59 | ENCODER_OBJECT_ID_HDMI_SI1930 = 0x11,
60 | ENCODER_OBJECT_ID_HDMI_INTERNAL = 0x12,
61 | /* Kaleidoscope (KLDSCP) Class Display Hardware (internal) */
62 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 = 0x13,
63 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 = 0x14,
64 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 = 0x15,
65 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 = 0x16, /* Shared with CV/TV and CRT */
66 | ENCODER_OBJECT_ID_SI178 = 0X17, /* External TMDS (dual link, no HDCP.) */
67 | ENCODER_OBJECT_ID_MVPU_FPGA = 0x18, /* MVPU FPGA chip */
68 | ENCODER_OBJECT_ID_INTERNAL_DDI = 0x19,
69 | ENCODER_OBJECT_ID_VT1625 = 0x1A,
70 | ENCODER_OBJECT_ID_HDMI_SI1932 = 0x1B,
71 | ENCODER_OBJECT_ID_DP_AN9801 = 0x1C,
72 | ENCODER_OBJECT_ID_DP_DP501 = 0x1D,
73 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY = 0x1E,
74 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA = 0x1F,
75 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 = 0x20,
76 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 = 0x21,
77 | ENCODER_OBJECT_ID_ALMOND = 0x22,
78 | ENCODER_OBJECT_ID_NUTMEG = 0x22,
79 | ENCODER_OBJECT_ID_TRAVIS = 0x23,
80 | ENCODER_OBJECT_ID_INTERNAL_VCE = 0x24,
81 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 = 0x25,
82 | ENCODER_OBJECT_ID_INTERNAL_AMCLK = 0x27
83 | };
84 |
85 | enum {
86 | CONNECTOR_OBJECT_ID_NONE = 0x00,
87 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I = 0x01,
88 | CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I = 0x02,
89 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D = 0x03,
90 | CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D = 0x04,
91 | CONNECTOR_OBJECT_ID_VGA = 0x05,
92 | CONNECTOR_OBJECT_ID_COMPOSITE = 0x06,
93 | CONNECTOR_OBJECT_ID_SVIDEO = 0x07,
94 | CONNECTOR_OBJECT_ID_YPbPr = 0x08,
95 | CONNECTOR_OBJECT_ID_D_CONNECTOR = 0x09,
96 | CONNECTOR_OBJECT_ID_9PIN_DIN = 0x0A, /* Supports both CV & TV */
97 | CONNECTOR_OBJECT_ID_SCART = 0x0B,
98 | CONNECTOR_OBJECT_ID_HDMI_TYPE_A = 0x0C,
99 | CONNECTOR_OBJECT_ID_HDMI_TYPE_B = 0x0D,
100 | CONNECTOR_OBJECT_ID_LVDS = 0x0E,
101 | CONNECTOR_OBJECT_ID_7PIN_DIN = 0x0F,
102 | CONNECTOR_OBJECT_ID_PCIE_CONNECTOR = 0x10,
103 | CONNECTOR_OBJECT_ID_CROSSFIRE = 0x11,
104 | CONNECTOR_OBJECT_ID_HARDCODE_DVI = 0x12,
105 | CONNECTOR_OBJECT_ID_DISPLAYPORT = 0x13,
106 | CONNECTOR_OBJECT_ID_eDP = 0x14,
107 | CONNECTOR_OBJECT_ID_MXM = 0x15,
108 | CONNECTOR_OBJECT_ID_LVDS_eDP = 0x16
109 | };
110 |
111 | // Initially applecon data is nulled.
112 | IOReturn AtiBiosParser2::translateAtomConnectorInfo(AtiBiosParser2 *parser, AtomConnectorInfo *atomcon, ModernConnector *applecon) {
113 | if (((atomcon->usConnObjectId & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT) != GRAPH_OBJECT_TYPE_CONNECTOR)
114 | return kIOReturnNotFound;
115 |
116 | uint8_t *i2cRecord = atomcon->i2cRecord;
117 | if (i2cRecord) {
118 | applecon->sense = (i2cRecord[2] & 0xF) + 1;
119 | } else {
120 | applecon->sense = 0;
121 | kprintf("ATOM: %s: ASSERT(NULL != i2cRecord)\n", "uint8_t AtiBiosParser2::getAuxDdcLine(atom_i2c_record *)");
122 | }
123 |
124 | uint8_t *hpdRecord = atomcon->hpdRecord;
125 | if (hpdRecord) {
126 | applecon->hotplug = hpdRecord[2];
127 | } else {
128 | applecon->hotplug = 0;
129 | kprintf("ATOM: %s: ASSERT(NULL != hpdRecord)\n", "uint8_t AtiBiosParser2::getHotPlugPin(atom_hpd_int_record *)");
130 | }
131 |
132 | AtiBiosParser2::getOutputInformation(parser, atomcon, applecon);
133 | AtiBiosParser2::getConnectorFeatures(parser, atomcon, applecon);
134 |
135 | if (applecon->flags) {
136 | if ((applecon->flags & 0x704) && applecon->hotplug)
137 | applecon->features |= 0x100;
138 | return kIOReturnSuccess;
139 | } else {
140 | kprintf("ATOM: %s: ASSERT(0 != drvInfo.connections)\n", "IOReturn AtiBiosParser2::translateAtomConnectorInfo(AtiObjectInfoTableInterface_V2::AtomConnectorInfo &, ConnectorInfo &)");
141 | }
142 |
143 | return kIOReturnNotFound;
144 | }
145 |
146 | IOReturn AtiBiosParser2::getOutputInformation(AtiBiosParser2 *parser, AtomConnectorInfo *atomcon, ModernConnector *applecon) {
147 | if (!atomcon->usGraphicObjIds) {
148 | kprintf("ATOM: %s: ASSERT(0 != objId.u16All)\n", "IOReturn AtiBiosParser2::getOutputInformation(AtiObjectInfoTableInterface_V2::AtomConnectorInfo &, ConnectorInfo &)");
149 | return kIOReturnBadArgument;
150 | }
151 |
152 | uint8_t encoder = atomcon->usGraphicObjIds;
153 | bool one = ((atomcon->usGraphicObjIds & ENUM_ID_MASK) >> ENUM_ID_SHIFT) == 1;
154 |
155 | switch (encoder) {
156 | case ENCODER_OBJECT_ID_NUTMEG:
157 | applecon->flags |= 0x10;
158 | return kIOReturnSuccess;
159 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
160 | if (one) {
161 | applecon->transmitter |= 0x10;
162 | } else {
163 | applecon->transmitter |= 0x20;
164 | applecon->encoder |= 0x1;
165 | }
166 | return kIOReturnSuccess;
167 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
168 | if (one) {
169 | applecon->transmitter |= 0x11;
170 | applecon->encoder |= 0x2;
171 | } else {
172 | applecon->transmitter |= 0x21;
173 | applecon->encoder |= 0x3;
174 | }
175 | return kIOReturnSuccess;
176 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
177 | if (one) {
178 | applecon->transmitter |= 0x12;
179 | applecon->encoder |= 0x4;
180 | } else {
181 | applecon->transmitter |= 0x22;
182 | applecon->encoder |= 0x5;
183 | }
184 | return kIOReturnSuccess;
185 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
186 | if (one) {
187 | applecon->transmitter |= 0x13;
188 | applecon->encoder |= 0x6;
189 | } else {
190 | applecon->transmitter |= 0x23;
191 | applecon->encoder |= 0x7;
192 | }
193 | return kIOReturnSuccess;
194 | }
195 |
196 | return kIOReturnInvalid;
197 | }
198 |
199 | IOReturn AtiBiosParser2::getConnectorFeatures(AtiBiosParser2 *parser, AtomConnectorInfo *atomcon, ModernConnector *applecon) {
200 | if (!atomcon->usConnObjectId) {
201 | kprintf("ATOM: %s: ASSERT(0 != objId.u16All)\n", "IOReturn AtiBiosParser2::getConnectorFeatures(AtiObjectInfoTableInterface_V2::AtomConnectorInfo &, ConnectorInfo &)");
202 | return kIOReturnBadArgument;
203 | }
204 |
205 | uint8_t connector = atomcon->usGraphicObjIds;
206 |
207 | switch (connector) {
208 | case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I:
209 | case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D:
210 | applecon->type = ConnectorDigitalDVI;
211 | applecon->flags |= 4;
212 | // unlock 2k res, causes crashes on R9 290X
213 | // undone by -raddvi
214 | applecon->transmitter &= 0xCF;
215 | return kIOReturnSuccess;
216 | case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I:
217 | case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D:
218 | applecon->type = ConnectorDigitalDVI;
219 | applecon->flags |= 4;
220 | return kIOReturnSuccess;
221 | case CONNECTOR_OBJECT_ID_HDMI_TYPE_A:
222 | case CONNECTOR_OBJECT_ID_HDMI_TYPE_B:
223 | applecon->type = ConnectorHDMI;
224 | applecon->flags |= 0x204;
225 | return kIOReturnSuccess;
226 | case CONNECTOR_OBJECT_ID_VGA:
227 | applecon->type = ConnectorVGA;
228 | applecon->flags |= 0x10;
229 | return kIOReturnSuccess;
230 | case CONNECTOR_OBJECT_ID_LVDS:
231 | applecon->type = ConnectorLVDS;
232 | applecon->flags |= 0x40;
233 | applecon->features |= 0x9;
234 | // unlock 2k res
235 | applecon->transmitter &= 0xCF;
236 | return kIOReturnSuccess;
237 | case CONNECTOR_OBJECT_ID_DISPLAYPORT:
238 | applecon->type = ConnectorDP;
239 | applecon->flags |= 0x304;
240 | return kIOReturnSuccess;
241 | case CONNECTOR_OBJECT_ID_eDP:
242 | applecon->type = ConnectorLVDS;
243 | applecon->flags |= 0x100;
244 | applecon->features |= 0x109;
245 | return kIOReturnSuccess;
246 | }
247 |
248 | return kIOReturnInvalid;
249 | }
250 |
--------------------------------------------------------------------------------
/Prebuilt/BoardHash:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acidanthera/WhateverGreen/bc1b7c334eefd00a9cf30429d686764c18ed59ae/Prebuilt/BoardHash
--------------------------------------------------------------------------------
/Prebuilt/WhateverName.app/Contents/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | WhateverName
9 | CFBundleIconFile
10 | icon
11 | CFBundleIdentifier
12 | as.vit9696.WhateverName
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | WhateverName
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | LSMinimumSystemVersion
26 | 10.10
27 | NSHumanReadableCopyright
28 | Copyright 2017 WhateverGreen Project
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Prebuilt/WhateverName.app/Contents/MacOS/WhateverName:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | RUNDIR=$(dirname "$0")
4 | pushd "$RUNDIR" >/dev/null
5 | RUNDIR=$(pwd)
6 | popd >/dev/null
7 |
8 | function msg() {
9 | if [ "$2" != "" ]; then
10 | icon="with icon $2"
11 | fi
12 |
13 | osascript < HDMI)
25 | - Fixes NVIDIA GPU interface stuttering on 10.13 (official and web drivers)
26 | - Fixes the kernel panic caused by an invalid link rate reported by DPCD on some laptops with Intel IGPU.
27 | - Fixes the infinite loop on establishing Intel HDMI connections with a higher pixel clock rate on Skylake, Kaby Lake and Coffee Lake platforms.
28 | - Implements the driver support for onboard LSPCON chips to enable DisplayPort to HDMI 2.0 output on some platforms with Intel IGPU.
29 | - Enforces complete modeset on non-built-in displays on Kaby Lake and newer to fix booting to black screen.
30 | - Allows non-supported cards to use HW video encoder (`-radcodec`)
31 | - Fixes choppy video playback on Intel Kaby Lake and newer.
32 | - Fixes black screen on Intel HD since 10.15.5.
33 | - Adds workaround for rare force wake timeout panics on Intel KBL and CFL.
34 | - Supports all valid Core Display Clock (CDCLK) freqencies on Intel ICL platforms.
35 | - Fixes the kernel panic caused by an incorrectly calculated amount of DVMT pre-allocated memory on Intel ICL platforms.
36 | - Makes brightness transitions smoother on Intel IVB+ platforms.
37 | - Fixes the short period garbled screen issue after the system boots on Intel ICL platforms.
38 | - Fixes the PWM backlight control of the built-in display that is directly wired to AMD Radeon RX 5000 series graphic cards.
39 | - Fixes the freeze during iGPU initialization that may occur on certain laptops such as Chromebooks on macOS 10.15 and later.
40 |
41 | #### Documentation
42 |
43 | Read [FAQs](./Manual/) and avoid asking any questions. No support is provided for the time being.
44 |
45 | #### Boot arguments
46 |
47 | ##### Global
48 |
49 | | Boot argument | DeviceProperties | Description |
50 | |--- |--- |--- |
51 | | `-cdfon` | `enable-hdmi20` | Enable HDMI 2.0 patches on iGPU and dGPU (Not implemented for macOS 11+) |
52 | | `-wegbeta` | N/A | Enable WhateverGreen on unsupported OS versions (15 and below are enabled by default) |
53 | | `-wegdbg` | N/A | Enable debug printing (available in DEBUG binaries) |
54 | | `-wegoff` | N/A | Disable WhateverGreen |
55 |
56 | ##### Switch GPU
57 |
58 | | Boot argument | DeviceProperties | Description |
59 | |--- |--- |--- |
60 | | `-wegnoegpu` | `disable-gpu` property to each GFX0 | Disable all external GPUs |
61 | | `-wegnoigpu` | `disable-gpu` property to IGPU | Disable internal GPU |
62 | | `-wegswitchgpu` | `switch-to-external-gpu` property to IGPU | Disable internal GPU when external GPU is installed |
63 |
64 | ##### AMD Radeon
65 |
66 | | Boot argument | DeviceProperties | Description |
67 | |--- |--- |--- |
68 | | `-rad24` | N/A | Enforce 24-bit display mode |
69 | | `-radcodec` | N/A | Force the spoofed PID to be used in AMDRadeonVADriver |
70 | | `-raddvi` | N/A | Enable DVI transmitter correction (required for 290X, 370, etc.) |
71 | | `-radvesa` | N/A | Disable ATI/AMD video acceleration completely |
72 | | `radpg=15` | N/A | Disable several power-gating modes (see [FAQ Radeon](./Manual/FAQ.Radeon.en.md), required for Cape Verde GPUs: Radeon HD 7730/7750/7770/R7 250/R7 250X) |
73 |
74 | ##### Board-id
75 |
76 | | Boot argument | DeviceProperties | Description |
77 | |--- |--- |--- |
78 | | `agdpmod=ignore` | `agdpmod` property to external GPU | Disables AGDP patches (`vit9696,pikera` value is implicit default for external GPUs) |
79 | | `agdpmod=pikera` | `agdpmod` property to external GPU | Replaces `board-id` with `board-ix` |
80 | | `agdpmod=vit9696` | `agdpmod` property to external GPU | Disable check for `board-id` |
81 |
82 | ##### Nvidia
83 |
84 | | Boot argument | DeviceProperties | Description |
85 | |--- |--- |--- |
86 | | `-ngfxdbg` | N/A | Enable NVIDIA driver error logging |
87 | | `ngfxcompat=1` | `force-compat` | Ignore compatibility check in NVDAStartupWeb |
88 | | `ngfxgl=1` | `disable-metal` | Disable Metal support on NVIDIA |
89 | | `ngfxsubmit=0` | `disable-gfx-submit` | Disable interface stuttering fix on 10.13 |
90 |
91 | ##### Intel HD Graphics
92 |
93 | | Boot argument | DeviceProperties | Description |
94 | |--- |--- |--- |
95 | | `-igfxblr` | `enable-backlight-registers-fix` property on IGPU | Fix backlight registers on KBL, CFL and ICL platforms |
96 | | `-igfxbls` | `enable-backlight-smoother` property on IGPU | Make brightness transitions smoother on IVB+ platforms. [Read the manual](./Manual/FAQ.IntelHD.en.md#customize-the-behavior-of-the-backlight-smoother-to-improve-your-experience) |
97 | | `-igfxblt` | `enable-backlight-registers-alternative-fix` property on IGPU | An alternative to the Backlight Registers Fix and make Backlight Smoother work on KBL/CFL platforms running macOS 13.4 or later. [Read the manual](./Manual/FAQ.IntelHD.en.md#fix-the-3-minute-black-screen-issue-on-cfl-platforms-running-macos-134-or-later) |
98 | | `-igfxcdc` | `enable-cdclk-frequency-fix` property on IGPU | Support all valid Core Display Clock (CDCLK) frequencies on ICL platforms. [Read the manual](./Manual/FAQ.IntelHD.en.md#support-all-possible-core-display-clock-cdclk-frequencies-on-icl-platforms) |
99 | | `-igfxdbeo` | `enable-dbuf-early-optimizer` property on IGPU | Fix the Display Data Buffer (DBUF) issues on ICL+ platforms. [Read the manual](./Manual/FAQ.IntelHD.en.md#fix-the-issue-that-the-builtin-display-remains-garbled-after-the-system-boots-on-icl-platforms) |
100 | | `-igfxdump` | N/A | Dump IGPU framebuffer kext to `/var/log/AppleIntelFramebuffer_X_Y` (available in DEBUG binaries) |
101 | | `-igfxdvmt` | `enable-dvmt-calc-fix` property on IGPU | Fix the kernel panic caused by an incorrectly calculated amount of DVMT pre-allocated memory on Intel ICL platforms |
102 | | `-igfxfbdump` | N/A | Dump native and patched framebuffer table to ioreg at `IOService:/IOResources/WhateverGreen` |
103 | | `-igfxhdmidivs` | `enable-hdmi-dividers-fix` property on IGPU | Fix the infinite loop on establishing Intel HDMI connections with a higher pixel clock rate on SKL, KBL and CFL platforms |
104 | | `-igfxi2cdbg` | N/A | Enable verbose output in I2C-over-AUX transactions (only for debugging purposes) |
105 | | `-igfxlspcon` | `enable-lspcon-support` property on IGPU | Enable the driver support for onboard LSPCON chips.
[Read the manual](./Manual/FAQ.IntelHD.en.md#lspcon-driver-support-to-enable-displayport-to-hdmi-20-output-on-igpu) |
106 | | `-igfxmlr` | `enable-dpcd-max-link-rate-fix` property on IGPU | Apply the maximum link rate fix |
107 | | `-igfxmpc` | `enable-max-pixel-clock-override` and `max-pixel-clock-frequency` properties on IGPU | Increase max pixel clock (as an alternative to patching `CoreDisplay.framework` |
108 | | `-igfxnohdmi` | `disable-hdmi-patches` | Disable DP to HDMI conversion patches for digital sound |
109 | | `-igfxnotelemetryload` | `disable-telemetry-load` property on IGPU | Disables iGPU telemetry loading that may cause a freeze during startup on certain laptops such as Chromebooks
110 | | `-igfxsklaskbl` | N/A | Enforce Kaby Lake (KBL) graphics kext being loaded and used on Skylake models (KBL `device-id` and `ig-platform-id` are required. Not required on macOS 13 and above) |
111 | | `-igfxtypec` | N/A | Force DP connectivity for Type-C platforms |
112 | | `-igfxvesa` | N/A | Disable Intel Graphics acceleration |
113 | | `igfxagdc=0` | `disable-agdc` property on IGPU | Disable AGDC |
114 | | `igfxfcms=1` | `complete-modeset` property on IGPU | Force complete modeset on Skylake or Apple firmwares |
115 | | `igfxfcmsfbs=` | `complete-modeset-framebuffers` property on IGPU | Specify indices of connectors for which complete modeset must be enforced. Each index is a byte in a 64-bit word; for example, value `0x010203` specifies connectors 1, 2, 3. If a connector is not in the list, the driver's logic is used to determine whether complete modeset is needed. Pass `-1` to disable. |
116 | | `igfxframe=frame` | `AAPL,ig-platform-id` or `AAPL,snb-platform-id` property on IGPU | Inject a dedicated framebuffer identifier into IGPU (only for TESTING purposes) |
117 | | `igfxfw=2` | `igfxfw` property on IGPU | Force loading of Apple GuC firmware |
118 | | `igfxgl=1` | `disable-metal` | Disable Metal support on Intel |
119 | | `igfxmetal=1` | `enable-metal` | Force enable Metal support on Intel for offline rendering |
120 | | `igfxonln=1` | `force-online` property on IGPU | Force online status on all displays |
121 | | `igfxonlnfbs=MASK`| `force-online-framebuffers` property on IGPU | Specify indices of connectors for which online status is enforced. Format is similar to `igfxfcmsfbs` |
122 | | `igfxpavp=1` | `igfxpavp` property on IGPU | Force enable PAVP output |
123 | | `igfxrpsc=1` | `rps-control` property on IGPU | Enable RPS control patch (improves IGPU performance) |
124 | | `igfxsnb=0` | N/A | Disable IntelAccelerator name fix for Sandy Bridge CPUs |
125 |
126 | ##### Backlight
127 |
128 | | Boot argument | DeviceProperties | Description |
129 | |--- |--- |--- |
130 | | `applbkl=3` | `applbkl` property | Enable PWM backlight control of AMD Radeon RX 5000 series graphic cards [read here.](./Manual/FAQ.Radeon.en.md) |
131 | | `applbkl=0` | `applbkl` property on IGPU | Disable AppleBacklight.kext patches for IGPU.
In case of custom AppleBacklight profile [read here](./Manual/FAQ.OldPlugins.en.md) |
132 |
133 | ##### 2nd Boot stage
134 |
135 | | Boot argument | DeviceProperties | Description |
136 | |--- |--- |--- |
137 | | `gfxrst=1` | N/A | Prefer drawing Apple logo at 2nd boot stage instead of framebuffer copying |
138 | | `gfxrst=4` | N/A | Disable framebuffer init interaction during 2nd boot stage |
139 |
140 | ##### Misc
141 |
142 | | Boot argument | DeviceProperties | Description |
143 | |--- |--- |--- |
144 | | `wegtree=1` | `rebuild-device-tree` property | Force device renaming on Apple FW |
145 |
146 | #### Credits
147 |
148 | - [Apple](https://www.apple.com) for macOS
149 | - [AMD](https://www.amd.com) for ATOM VBIOS parsing code
150 | - [The PCI ID Repository](http://pci-ids.ucw.cz) for multiple GPU model names
151 | - [Andrey1970AppleLife](https://github.com/Andrey1970AppleLife) for [FAQs](./Manual/)
152 | - [FireWolf](https://github.com/0xFireWolf/) for the DPCD maximum link rate fix, infinite loop fix for Intel HDMI connections, LSPCON driver support, Core Display Clock frequency fix for ICL platforms, DVMT pre-allocated memory calculation fix for ICL platforms, Backlight Smoother for IVB+ platforms, Display Data Buffer fix for ICL platforms, and Backlight Registers Alternative Fix.
153 | - [Floris497](https://github.com/Floris497) for the CoreDisplay [patches](https://github.com/Floris497/mac-pixel-clock-patch-v2)
154 | - [Fraxul](https://github.com/Fraxul) for original CFL backlight patch
155 | - [headkaze](https://github.com/headkaze) for Intel framebuffer patching code and CFL backlight patch improvements
156 | - [hieplpvip](https://github.com/hieplpvip) for initial AppleBacklight patching plugin
157 | - [igork](https://applelife.ru/members/igork.564/) for power-gating patch discovery and various FP research
158 | - [lvs1974](https://applelife.ru/members/lvs1974.53809) for continuous implementation of Intel and NVIDIA fixing code
159 | - [mologie](https://github.com/mologie/NVWebDriverLibValFix) for creating NVWebDriverLibValFix.kext which forces macOS to recognize NVIDIA's web drivers as platform binaries
160 | - [PMheart](https://github.com/PMheart) for CoreDisplay patching code and Intel fix backporting
161 | - [RehabMan](https://github.com/RehabMan) for various enhancements
162 | - [RemB](https://applelife.ru/members/remb.8064/) for continuing sleep-wake research and finding the right register for AMD issues
163 | - [Vandroiy](https://applelife.ru/members/vandroiy.83653/) for maintaining the GPU model detection database
164 | - [YungRaj](https://github.com/YungRaj) and [syscl](https://github.com/syscl) for Intel fix backporting
165 | - [vit9696](https://github.com/vit9696) for writing the software and maintaining it
166 |
--------------------------------------------------------------------------------
/ResourceConverter/generate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # generate.sh
4 | # WhateverGreen
5 | #
6 | # Copyright © 2018 vit9696. All rights reserved.
7 |
8 | ret=0
9 |
10 | rm -f "${PROJECT_DIR}/WhateverGreen/kern_resources.cpp"
11 |
12 | "${TARGET_BUILD_DIR}/ResourceConverter" \
13 | "${PROJECT_DIR}/Resources" \
14 | "${PROJECT_DIR}/WhateverGreen/kern_resources.cpp" \
15 | "${PROJECT_DIR}/WhateverGreen/kern_resources.hpp" || ret=1
16 |
17 | if (( $ret )); then
18 | echo "Failed to build kern_resources.cpp"
19 | exit 1
20 | fi
21 |
--------------------------------------------------------------------------------
/ResourceConverter/main.mm:
--------------------------------------------------------------------------------
1 | //
2 | // main.mm
3 | // ResourceConverter
4 | //
5 | // Copyright © 2018 vit9696. All rights reserved.
6 | //
7 |
8 | //This file is a shameful terribly written copy-paste-like draft with minimal error checking if at all
9 | //TODO: Rewrite this completely
10 |
11 | #import
12 | #import
13 | #include
14 |
15 | #define SYSLOG(str, ...) printf("ResourceConverter: " str "\n", ## __VA_ARGS__)
16 | #define ERROR(str, ...) do { SYSLOG(str, ## __VA_ARGS__); exit(1); } while(0)
17 | NSString *ResourceHeader {@"\
18 | // \n\
19 | // kern_resources.cpp \n\
20 | // WhateverGreen \n\
21 | // \n\
22 | // Copyright © 2018 vit9696. All rights reserved. \n\
23 | // \n\
24 | // This is an autogenerated file! \n\
25 | // Please avoid any modifications! \n\
26 | // \n\n\
27 | #include \"kern_resources.hpp\" \n\n"
28 | };
29 |
30 | NSString *ResourcePrivHeader {@"\
31 | // \n\
32 | // kern_resources.hpp \n\
33 | // WhateverGreen \n\
34 | // \n\
35 | // Copyright © 2018 vit9696. All rights reserved. \n\
36 | // \n\
37 | // This is an autogenerated file! \n\
38 | // Please avoid any modifications! \n\
39 | // \n\n\
40 | #include \n\
41 | #include \n\n\
42 | extern UserPatcher::BinaryModInfo ADDPR(binaryMod)[];\n\
43 | extern const size_t ADDPR(binaryModSize); \n\n\
44 | extern UserPatcher::ProcInfo ADDPR(procInfoModern)[];\n\
45 | extern const size_t ADDPR(procInfoModernSize); \n\n\
46 | extern UserPatcher::ProcInfo ADDPR(procInfoLegacy)[];\n\
47 | extern const size_t ADDPR(procInfoLegacySize); \n\n"
48 | //extern const uint32_t minProcLength; \n"
49 | };
50 |
51 | static void appendFile(NSString *file, NSString *data) {
52 | NSFileHandle *handle = [NSFileHandle fileHandleForUpdatingAtPath:file];
53 | [handle seekToEndOfFile];
54 | [handle writeData:[data dataUsingEncoding:NSUTF8StringEncoding]];
55 | [handle closeFile];
56 | }
57 |
58 | static NSString *generatePatchEntries(NSString *file, NSArray *patches) {
59 | static size_t patchIndex {0};
60 | static size_t patchBufIndex {0};
61 |
62 | if (patches) {
63 | auto pStr = [[[NSMutableString alloc] initWithFormat:@"static UserPatcher::BinaryModPatch patches%zu[] {\n", patchIndex] autorelease];
64 | auto pbStr = [[[NSMutableString alloc] init] autorelease];
65 | for (NSDictionary *p in patches) {
66 | if ([p objectForKey:@"Disable"])
67 | continue;
68 |
69 | NSData *f[] = {[p objectForKey:@"Find"], [p objectForKey:@"Replace"]};
70 |
71 | if ([f[0] length] != [f[1] length]) {
72 | [pStr appendString:@"#error not matching patch lengths\n"];
73 | continue;
74 | }
75 |
76 | for (auto d : f) {
77 | [pbStr appendString:[[[NSString alloc] initWithFormat:@"alignas(8) static const uint8_t patchBuf%zu[] { ", patchBufIndex] autorelease]];
78 |
79 | for (size_t b = 0; b < [d length]; b++) {
80 | [pbStr appendString:[[[NSString alloc] initWithFormat:@"0x%0.2X, ", reinterpret_cast([d bytes])[b]] autorelease]];
81 | }
82 |
83 | [pbStr appendString:@"};\n"];
84 |
85 | patchBufIndex++;
86 | }
87 |
88 | [pStr appendFormat:@"\t{ %@, %@, patchBuf%zu, patchBuf%zu, %zu, %@, %@, UserPatcher::FileSegment::Segment%@, Section%@ },\n",
89 | [p objectForKey:@"CPU"],
90 | [p objectForKey:@"Flags"] ?: @"0",
91 | patchBufIndex-2,
92 | patchBufIndex-1,
93 | [f[0] length],
94 | [p objectForKey:@"Skip"] ?: @"0",
95 | [p objectForKey:@"Count"],
96 | [p objectForKey:@"Segment"] ?: @"TextText",
97 | [p objectForKey:@"Section"]
98 | ];
99 | }
100 | [pStr appendString:@"};\n"];
101 |
102 | appendFile(file, pbStr);
103 | appendFile(file, pStr);
104 | patchIndex++;
105 | return [[[NSString alloc] initWithFormat:@"patches%zu, %lu", patchIndex-1, [patches count]] autorelease];
106 | }
107 |
108 | return @"nullptr, 0";
109 | }
110 |
111 | static void generateMods(NSString *file, NSString *header, NSArray *modInfos, NSMutableDictionary *sections) {
112 |
113 |
114 | for (NSDictionary *entry in modInfos) {
115 | if ([entry objectForKey:@"Disable"])
116 | continue;
117 |
118 | NSArray *patches = [entry objectForKey:@"Patches"];
119 | for (NSDictionary *patch in patches)
120 | [sections setObject:@"ok" forKey:[patch objectForKey:@"Section"]];
121 | }
122 |
123 | appendFile(file, @"\n// Patch section\n\n");
124 |
125 | auto modSection = [[[NSMutableString alloc] initWithUTF8String:"\n// Mod section\n\n"] autorelease];
126 | [modSection appendString:@"UserPatcher::BinaryModInfo ADDPR(binaryMod)[] {\n"];
127 |
128 | size_t modCount = 0;
129 |
130 | for (NSDictionary *entry in modInfos) {
131 | if ([entry objectForKey:@"Disable"])
132 | continue;
133 |
134 | NSArray *patches = [entry objectForKey:@"Patches"];
135 | [modSection appendFormat:@"\t{ \"%@\", %@ },\n",
136 | [entry objectForKey:@"Path"], generatePatchEntries(file, patches)];
137 |
138 | modCount++;
139 | }
140 |
141 | [modSection appendString:@"};\n"];
142 | [modSection appendFormat:@"\nconst size_t ADDPR(binaryModSize) {%lu};\n", modCount];
143 | appendFile(file, modSection);
144 | }
145 |
146 | static void generateComparison(NSString *file, NSArray *binaries, NSMutableDictionary *sections, bool modern) {
147 | auto procSection = [[[NSMutableString alloc] initWithUTF8String:"\n// Process list\n"
148 | "using PF = UserPatcher::ProcInfo::ProcFlags;\n\n"] autorelease];
149 | NSUInteger minProcLength {PATH_MAX};
150 | size_t procCount = 0;
151 |
152 | [procSection appendFormat:@"UserPatcher::ProcInfo ADDPR(procInfo%s)[] {\n", modern ? "Modern" : "Legacy"];
153 |
154 | for (NSDictionary *entry in binaries) {
155 | if ([entry objectForKey:@"Disable"])
156 | continue;
157 |
158 | NSString *type = [entry objectForKey:@"Type"];
159 | if (type) {
160 | if (modern && ![type isEqualToString:@"Modern"])
161 | continue;
162 | if (!modern && ![type isEqualToString:@"Legacy"])
163 | continue;
164 | }
165 |
166 | [sections setObject:@"ok" forKey:[entry objectForKey:@"Section"]];
167 |
168 | auto len = [[entry objectForKey:@"Path"] length];
169 | NSString *prefix = [entry objectForKey:modern ? @"ModernPrefix" : @"LegacyPrefix"];
170 | if (prefix)
171 | len += [prefix length];
172 | NSString *flags = [entry objectForKey:@"Flags"];
173 | [procSection appendFormat:@"\t{ \"%@%@\", %lu, Section%@, %@ },\n",
174 | prefix ? prefix : @"", [entry objectForKey:@"Path"], len, [entry objectForKey:@"Section"],
175 | flags ? flags : @"PF::MatchExact"];
176 | if (len < minProcLength)
177 | minProcLength = len;
178 |
179 | procCount++;
180 | }
181 | [procSection appendString:@"};\n"];
182 | [procSection appendFormat:@"\nconst size_t ADDPR(procInfo%sSize) {%lu};", modern ? "Modern" : "Legacy", procCount];
183 | //[procSection appendFormat:@"\nconst uint32_t minProcLength {%lu};\n", minProcLength];
184 |
185 |
186 | appendFile(file, procSection);
187 | }
188 |
189 | int main(int argc, const char * argv[]) {
190 | @autoreleasepool {
191 | if (argc != 4)
192 | ERROR("Invalid usage");
193 |
194 | auto basePath = [[[NSString alloc] initWithUTF8String:argv[1]] autorelease];
195 | auto patchesCfg = [[[NSString alloc] initWithFormat:@"%@/Patches.plist", basePath] autorelease];
196 | auto outputCpp = [[[NSString alloc] initWithUTF8String:argv[2]] autorelease];
197 | auto outputHpp = [[[NSString alloc] initWithUTF8String:argv[3]] autorelease];
198 |
199 | NSDictionary *patches = [NSDictionary dictionaryWithContentsOfFile:patchesCfg];
200 |
201 | if (!patches)
202 | ERROR("Missing resource data");
203 |
204 | // Create a file
205 | [[NSFileManager defaultManager] createFileAtPath:outputCpp contents:nil attributes:nil];
206 | [[NSFileManager defaultManager] createFileAtPath:outputHpp contents:nil attributes:nil];
207 |
208 | auto sections = [[[NSMutableDictionary alloc] init] autorelease];
209 |
210 | appendFile(outputCpp, ResourceHeader);
211 | appendFile(outputHpp, ResourcePrivHeader);
212 | generateMods(outputCpp, outputHpp, [patches objectForKey:@"Patches"], sections);
213 | generateComparison(outputCpp, [patches objectForKey:@"Processes"], sections, false);
214 | generateComparison(outputCpp, [patches objectForKey:@"Processes"], sections, true);
215 |
216 | auto sectionList = [[[NSMutableString alloc] initWithUTF8String:"\n// Section list\n\nenum : uint32_t {\n\tSectionUnused = 0,\n"] autorelease];
217 | size_t sectionIndex = 1;
218 | for (NSString *entry in sections)
219 | [sectionList appendFormat:@"\tSection%@ = %lu,\n", entry, sectionIndex++];
220 | [sectionList appendString:@"};\n"];
221 | appendFile(outputHpp, sectionList);
222 | }
223 | }
224 |
--------------------------------------------------------------------------------
/Tools/BoardHash/BoardHash.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | void calcHash(const char * board) {
6 | CC_SHA1_CTX ctx;
7 | size_t len = strlen(board) + 1;
8 | CC_SHA1_Init(&ctx);
9 | CC_SHA1_Update(&ctx, board, len);
10 | unsigned char md[CC_SHA1_DIGEST_LENGTH];
11 | CC_SHA1_Final(md, &ctx);
12 | printf("board-id hash: ");
13 | for (size_t i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
14 | printf("%02x", md[i]);
15 | }
16 | printf(" = %zu\n", len);
17 | }
18 |
19 | int main(int argc, char *argv[]) {
20 | if (argc != 2) {
21 | puts("Usage: ./BoardHash Mac-BOARDID");
22 | } else {
23 | calcHash(argv[1]);
24 | }
25 | }
--------------------------------------------------------------------------------
/Tools/BoardHash/build.tool:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | cd "$(dirname "$0")"
4 | clang -s -flto -mmacosx-version-min=10.9 -Os BoardHash.c -o BoardHash
5 |
--------------------------------------------------------------------------------
/Tools/GPUInfo/build.tool:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd "$(dirname "$0")"
4 | rm -rf gpuinfo32 gpuinfo64 gpuinfo *.dSYM
5 |
6 | if [ "$DEBUG" != "" ]; then
7 | #clang -Wall -Wextra -pedantic -Wl,-framework,CoreFoundation -Wl,-framework,IOKit -lobjc -m32 -O0 -mmacosx-version-min=10.4 gpuinfo.c -o gpuinfo32 || exit 1
8 | clang -Wall -Wextra -pedantic -Wl,-framework,CoreFoundation -Wl,-framework,IOKit -lobjc -m64 -O0 -mmacosx-version-min=10.4 gpuinfo.c -o gpuinfo64 || exit 1
9 | else
10 | #clang -Wall -Wextra -pedantic -Wl,-framework,CoreFoundation -Wl,-framework,IOKit -lobjc -m32 -flto -O3 -mmacosx-version-min=10.4 gpuinfo.c -o gpuinfo32 || exit 1
11 | clang -Wall -Wextra -pedantic -Wl,-framework,CoreFoundation -Wl,-framework,IOKit -lobjc -m64 -flto -O0 -mmacosx-version-min=10.4 gpuinfo.c -o gpuinfo64 || exit 1
12 | fi
13 |
14 | #strip -x gpuinfo32 || exit 1
15 | strip -x gpuinfo64 || exit 1
16 |
17 | #lipo -create gpuinfo32 gpuinfo64 -output gpuinfo || exit 1
18 | mv gpuinfo64 gpuinfo || exit 1
19 |
20 | rm -f gpuinfo32 gpuinfo64
21 |
22 | exit 0
23 |
--------------------------------------------------------------------------------
/Tools/GPUInfo/gpuinfo.c:
--------------------------------------------------------------------------------
1 | //
2 | // GPU Info
3 | // Based on freevram and MetalInfo tools.
4 | // See: https://stackoverflow.com/questions/3783030/free-vram-on-os-x
5 | //
6 |
7 | #define OBJC_OLD_DISPATCH_PROTOTYPES 1
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #include
15 | #include
16 |
17 | #include
18 | #include
19 |
20 | uint64_t currentFreeVRAM(uint64_t *total) {
21 | kern_return_t krc;
22 | mach_port_t masterPort;
23 | krc = IOMasterPort(bootstrap_port, &masterPort);
24 |
25 | if (total)
26 | *total = 0;
27 |
28 | if (krc == KERN_SUCCESS) {
29 | CFMutableDictionaryRef pattern = IOServiceMatching(kIOAcceleratorClassName);
30 |
31 | io_iterator_t deviceIterator;
32 | krc = IOServiceGetMatchingServices(masterPort, pattern, &deviceIterator);
33 | if (krc == KERN_SUCCESS) {
34 | io_object_t object;
35 | while ((object = IOIteratorNext(deviceIterator))) {
36 | CFMutableDictionaryRef properties = NULL;
37 | krc = IORegistryEntryCreateCFProperties(object, &properties, kCFAllocatorDefault, (IOOptionBits)0);
38 | if (krc == KERN_SUCCESS) {
39 | const void *total_vram_number = CFDictionaryGetValue(properties, CFSTR("VRAM,totalMB"));
40 | if (total_vram_number)
41 | CFNumberGetValue((CFNumberRef) total_vram_number, kCFNumberSInt64Type, total);
42 | CFMutableDictionaryRef perf_properties = (CFMutableDictionaryRef)CFDictionaryGetValue(properties, CFSTR("PerformanceStatistics") );
43 |
44 | // Look for a number of keys (this is mostly reverse engineering and best-guess effort)
45 | const void *free_vram_number = CFDictionaryGetValue(perf_properties, CFSTR("vramFreeBytes"));
46 | if (free_vram_number) {
47 | ssize_t vramFreeBytes;
48 | CFNumberGetValue((CFNumberRef)free_vram_number, kCFNumberSInt64Type, &vramFreeBytes);
49 | return vramFreeBytes;
50 | }
51 | }
52 | if (properties)
53 | CFRelease(properties);
54 | IOObjectRelease(object);
55 | }
56 | IOObjectRelease(deviceIterator);
57 | }
58 | }
59 | return 0;
60 | }
61 |
62 | void printInfo(void) {
63 | uint64_t total_vram = 0;
64 | uint64_t free_vram = currentFreeVRAM(&total_vram);
65 | if (total_vram > 0)
66 | printf("Total VRAM available: %zu MB\n", (size_t)total_vram);
67 | if (free_vram > 0)
68 | printf("Free VRAM available: %zu MB (%zu Bytes)\n", (size_t)(free_vram/(1024*1024)), (size_t)free_vram);
69 |
70 | void *mtl = dlopen("/System/Library/Frameworks/Metal.framework/Metal", RTLD_LAZY);
71 | id (*create_dev)(void) = (id (*)(void))dlsym(mtl, "MTLCreateSystemDefaultDevice");
72 | if (create_dev) {
73 | id device = create_dev();
74 | if (device) {
75 | id name = objc_msgSend(device, sel_registerName("name"));
76 | id lowpower = objc_msgSend(device, sel_registerName("isLowPower"));
77 | id headless = objc_msgSend(device, sel_registerName("isHeadless"));
78 | printf("Metal device name: %s\n", (const char *)objc_msgSend(name, sel_registerName("UTF8String")));
79 | printf("Low Power: %s\n", lowpower ? "Yes" : "No");
80 | printf("Headless: %s\n", headless ? "Yes" : "No");
81 | } else {
82 | printf("Metal is not supported by your hardware!\n");
83 | }
84 | } else {
85 | printf("Metal is not supported by this operating system!\n");
86 | }
87 | }
88 |
89 | int main(int argc, char *argv[]) {
90 | if (argc > 1 && !strcmp(argv[1], "-l")) {
91 | while (1) {
92 | system("clear");
93 | printInfo();
94 | sleep(1);
95 | }
96 | } else {
97 | printInfo();
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/Tools/HookMac/HookMac.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include "rd_route.h"
8 |
9 | uint8_t customMac[] = {0x00, 0x25, 0x00, 0x00, 0x00, 0x00};
10 |
11 | CFTypeRef (*org_IORegistryEntryCreateCFProperty)(io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options);
12 | CFTypeRef my_IORegistryEntryCreateCFProperty(io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options) {
13 | CFTypeRef obj = org_IORegistryEntryCreateCFProperty(entry, key, allocator, options);
14 | if (kCFCompareEqualTo == CFStringCompare(key, CFSTR("IOMACAddress"), 0)) {
15 | uint8_t *mac = (uint8_t *)CFDataGetBytePtr((CFDataRef)obj);
16 | printf("Routing mac address %0.2X:%0.2X:%0.2X:%0.2X:%0.2X:%0.2X to new one\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
17 | memcpy(mac, customMac, 6);
18 | }
19 |
20 | return obj;
21 | }
22 |
23 | __attribute__((constructor)) void start() {
24 | char *mac = getenv ("MAC");
25 |
26 | if (!mac || sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &customMac[0], &customMac[1], &customMac[2], &customMac[3], &customMac[4], &customMac[5]) != 6) {
27 | printf("Custom MAC address in MAC variable is either not provided or invalid, will randomise it\n");
28 | srand(time(NULL));
29 | customMac[3] = rand() % 256;
30 | customMac[4] = rand() % 256;
31 | customMac[5] = rand() % 256;
32 | }
33 |
34 | printf("Hi, I will hook your IOMACAddress to %0.2X:%0.2X:%0.2X:%0.2X:%0.2X:%0.2X\n", customMac[0], customMac[1], customMac[2], customMac[3], customMac[4], customMac[5]);
35 | if (rd_route((void *)IORegistryEntryCreateCFProperty, (void *)my_IORegistryEntryCreateCFProperty, (void **)&org_IORegistryEntryCreateCFProperty) != KERN_SUCCESS) {
36 | fprintf(stderr, "Failed to route IORegistryEntryCreateCFProperty\n");
37 | }
38 | }
--------------------------------------------------------------------------------
/Tools/HookMac/build.tool:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | cd "$(dirname "$0")"
4 | clang -s -flto -fvisibility=hidden -mmacosx-version-min=10.9 -dynamiclib -Os -framework IOKit -framework CoreFoundation HookMac.c rd_route.c -o libHookMac.dylib
--------------------------------------------------------------------------------
/Tools/HookMac/rd_route.h:
--------------------------------------------------------------------------------
1 | // rd_route.h
2 | // Copyright (c) 2014-2015 Dmitry Rodionov
3 | //
4 | // This software may be modified and distributed under the terms
5 | // of the MIT license. See the LICENSE file for details.
6 |
7 | #ifndef RD_ROUTE
8 | #define RD_ROUTE
9 |
10 | #ifdef __cplusplus
11 | extern "C" {
12 | #endif
13 |
14 | /**
15 | * Override `function` to jump directly into `replacement` location. Caller can later
16 | * access an original function's implementation via `original_ptr` (if passed).
17 | * Note that `original_ptr` won't be equal to `function` due to remapping the latter
18 | * into a different memory space.
19 | *
20 | * @param function pointer to a function to override;
21 | * @param replacement pointer to new implementation;
22 | * @param original will be set to an address of the original implementation's copy;
23 | *
24 | * @return KERN_SUCCESS if succeeded, or other value if failed
25 | */
26 | int rd_route(void *function, void *replacement, void **original);
27 |
28 | /**
29 | * The same as rd_route(), but the target function is defined with its name, not its symbol pointer.
30 | * If the `image_name` provided, rd_route_byname() looks for the function within it.
31 | * Otherwise it iterates all images loaded into the current process' address space and, if there is more
32 | * than one image containing a function with the specifed name, it will choose the first one.
33 | *
34 | * @param function_name name of a function to override;
35 | * @param image_name name of a mach-o image containing the function. It may be NULL, a full file path or
36 | * just a file name (e.g. "CoreFoundation");
37 | * @param replacement pointer to new implementation of the function;
38 | * @param original will be set to an address of the original implementation's copy;
39 | *
40 | * @return see rd_route() for the list of possible return values
41 | */
42 | int rd_route_byname(const char *function_name, const char *image_name, void *replacement, void **original);
43 |
44 | /**
45 | * Copy `function` implementation into another (first available) memory region.
46 | * @param function pointer to a function to override;
47 | * @param duplicate will be set to an address of the function's implementation copy
48 | *
49 | * @return KERN_SUCCESS if succeeded, or other value if failed
50 | */
51 | int rd_duplicate_function(void *function, void **duplicate);
52 |
53 | #ifdef __cplusplus
54 | }
55 | #endif
56 |
57 | #endif /* RD_ROUTE */
58 |
--------------------------------------------------------------------------------
/Tools/WhateverName/WhateverName.app/Contents/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | WhateverName
9 | CFBundleIconFile
10 | icon
11 | CFBundleIdentifier
12 | as.vit9696.WhateverName
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | WhateverName
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | LSMinimumSystemVersion
26 | 10.10
27 | NSHumanReadableCopyright
28 | Copyright 2017 WhateverGreen Project
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Tools/WhateverName/WhateverName.app/Contents/MacOS/WhateverName:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | RUNDIR=$(dirname "$0")
4 | pushd "$RUNDIR" >/dev/null
5 | RUNDIR=$(pwd)
6 | popd >/dev/null
7 |
8 | function msg() {
9 | if [ "$2" != "" ]; then
10 | icon="with icon $2"
11 | fi
12 |
13 | osascript </dev/null
5 | BUILDDIR=$(pwd)
6 | popd >/dev/null
7 |
8 | rm -f "$BUILDDIR/rd_route.32.o" "$BUILDDIR/rd_route.64.o" \
9 | "$BUILDDIR/WhateverName.32.o" "$BUILDDIR/WhateverName.64.o" \
10 | "$BUILDDIR/libWhateverName.32.dylib" "$BUILDDIR/libWhateverName.64.dylib" \
11 | "$BUILDDIR/libWhateverName.dylib" "$BUILDDIR/WhateverName.app/Contents/MacOS/libWhateverName.dylib"
12 |
13 | xcrun --sdk macosx cc -x c -c -std=c11 -arch x86_64 -mmacosx-version-min=10.10 -DNDEBUG=1 -flto -fvisibility=hidden $1 -O3 "$BUILDDIR/rd_route.c" -o "$BUILDDIR/rd_route.64.o" || exit 1
14 | xcrun --sdk macosx cc -x objective-c++ -c -std=c++14 -arch x86_64 -mmacosx-version-min=10.10 -DNDEBUG=1 -flto -fvisibility=hidden $1 -O3 "$BUILDDIR/WhateverName.mm" -o "$BUILDDIR/WhateverName.64.o" || exit 1
15 | xcrun --sdk macosx cc -arch x86_64 -mmacosx-version-min=10.10 -flto -fobjc-link-runtime -framework IOKit -lc++ $1 -O3 -dynamiclib "$BUILDDIR/rd_route.64.o" "$BUILDDIR/WhateverName.64.o" -o "$BUILDDIR/libWhateverName.64.dylib" || exit 1
16 | strip -x "$BUILDDIR/libWhateverName.64.dylib" || exit 1
17 |
18 | xcrun --sdk macosx cc -x c -c -std=c11 -arch i386 -mmacosx-version-min=10.10 -DNDEBUG=1 -flto -fvisibility=hidden $1 -O3 "$BUILDDIR/rd_route.c" -o "$BUILDDIR/rd_route.32.o" || exit 1
19 | xcrun --sdk macosx cc -x objective-c++ -c -std=c++14 -arch i386 -mmacosx-version-min=10.10 -DNDEBUG=1 -flto -fvisibility=hidden $1 -O3 "$BUILDDIR/WhateverName.mm" -o "$BUILDDIR/WhateverName.32.o" || exit 1
20 | xcrun --sdk macosx cc -arch i386 -mmacosx-version-min=10.10 -flto -fobjc-link-runtime -framework IOKit -lc++ $1 -O3 -dynamiclib "$BUILDDIR/rd_route.32.o" "$BUILDDIR/WhateverName.32.o" -o "$BUILDDIR/libWhateverName.32.dylib" || exit 1
21 | strip -x "$BUILDDIR/libWhateverName.32.dylib" || exit 1
22 |
23 | lipo -create "$BUILDDIR/libWhateverName.64.dylib" "$BUILDDIR/libWhateverName.32.dylib" -output "$BUILDDIR/libWhateverName.dylib" || exit 1
24 |
25 | rm -f "$BUILDDIR/rd_route.32.o" "$BUILDDIR/rd_route.64.o" \
26 | "$BUILDDIR/WhateverName.32.o" "$BUILDDIR/WhateverName.64.o" \
27 | "$BUILDDIR/libWhateverName.32.dylib" "$BUILDDIR/libWhateverName.64.dylib"
28 |
29 | mv "$BUILDDIR/libWhateverName.dylib" "$BUILDDIR/WhateverName.app/Contents/MacOS/libWhateverName.dylib"
30 |
31 | exit 0
32 |
--------------------------------------------------------------------------------
/Tools/WhateverName/rd_route.h:
--------------------------------------------------------------------------------
1 | // rd_route.h
2 | // Copyright (c) 2014-2015 Dmitry Rodionov
3 | //
4 | // This software may be modified and distributed under the terms
5 | // of the MIT license. See the LICENSE file for details.
6 |
7 | #ifndef RD_ROUTE
8 | #define RD_ROUTE
9 |
10 | #ifdef __cplusplus
11 | extern "C" {
12 | #endif
13 |
14 | /**
15 | * Override `function` to jump directly into `replacement` location. Caller can later
16 | * access an original function's implementation via `original_ptr` (if passed).
17 | * Note that `original_ptr` won't be equal to `function` due to remapping the latter
18 | * into a different memory space.
19 | *
20 | * @param function pointer to a function to override;
21 | * @param replacement pointer to new implementation;
22 | * @param original will be set to an address of the original implementation's copy;
23 | *
24 | * @return KERN_SUCCESS if succeeded, or other value if failed
25 | */
26 | int rd_route(void *function, void *replacement, void **original);
27 |
28 | /**
29 | * The same as rd_route(), but the target function is defined with its name, not its symbol pointer.
30 | * If the `image_name` provided, rd_route_byname() looks for the function within it.
31 | * Otherwise it iterates all images loaded into the current process' address space and, if there is more
32 | * than one image containing a function with the specifed name, it will choose the first one.
33 | *
34 | * @param function_name name of a function to override;
35 | * @param image_name name of a mach-o image containing the function. It may be NULL, a full file path or
36 | * just a file name (e.g. "CoreFoundation");
37 | * @param replacement pointer to new implementation of the function;
38 | * @param original will be set to an address of the original implementation's copy;
39 | *
40 | * @return see rd_route() for the list of possible return values
41 | */
42 | int rd_route_byname(const char *function_name, const char *image_name, void *replacement, void **original);
43 |
44 | /**
45 | * Copy `function` implementation into another (first available) memory region.
46 | * @param function pointer to a function to override;
47 | * @param duplicate will be set to an address of the function's implementation copy
48 | *
49 | * @return KERN_SUCCESS if succeeded, or other value if failed
50 | */
51 | int rd_duplicate_function(void *function, void **duplicate);
52 |
53 |
54 | /**
55 | * Get function pointer by its name
56 | *
57 | * @param function_name name of a function to look for;
58 | * @param image_name name of a mach-o image containing the function. It may be NULL, a full file path or
59 | * just a file name (e.g. "CoreFoundation");
60 | * @param result will be set to an address of the function;
61 | *
62 | * @return KERN_SUCCESS if succeeded, or other value if failed
63 | */
64 | int rd_function_byname(const char *function_name, const char *image_name, void **result);
65 |
66 | #ifdef __cplusplus
67 | }
68 | #endif
69 |
70 | #endif /* RD_ROUTE */
71 |
--------------------------------------------------------------------------------
/Tools/dump_platformlist.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #set -x
3 |
4 | function capture_ioreg_data
5 | # $1 is node name to search/capture
6 | # $2 is file name to save XML to
7 | {
8 | ioreg -n $1 -arxw0 >$2
9 | }
10 |
11 | function extract_bin_property
12 | # $1 is plist file name
13 | # $2 is path within
14 | # $3 is file name for binary output
15 | {
16 | local data=$(/usr/libexec/PlistBuddy -x -c "Print :$2" $1 2>&1)
17 | data=$([[ "$data" =~ \(.*)\<\/data\> ]] && echo ${BASH_REMATCH[1]})
18 | echo "$data" | base64 --decode >$3
19 | }
20 |
21 | plist=/tmp/org.rehabman.platformlist.plist
22 | capture_ioreg_data WhateverGreen $plist
23 | if [[ ! -s /tmp/org.rehabman.platformlist.plist ]]; then
24 | echo "Error capturing WhateverGreen registry data (WhateverGreen not installed?)"
25 | exit
26 | fi
27 |
28 | for x in native patched; do
29 | extract_bin_property $plist :0:platform-table-$x $x.bin
30 | xxd -groupsize 4 <$x.bin >$x.txt
31 | done
32 |
33 | #EOF
34 |
--------------------------------------------------------------------------------
/WhateverGreen/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | OSBundleCompatibleVersion
6 | 1.0
7 | CFBundleDevelopmentRegion
8 | en
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | KEXT
19 | CFBundleShortVersionString
20 | $(MODULE_VERSION)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(MODULE_VERSION)
25 | IOKitPersonalities
26 |
27 | as.vit9696.WhateverGreen
28 |
29 | CFBundleIdentifier
30 | $(PRODUCT_BUNDLE_IDENTIFIER)
31 | IOClass
32 | $(PRODUCT_NAME:rfc1034identifier)
33 | IOMatchCategory
34 | $(PRODUCT_NAME:rfc1034identifier)
35 | IOProviderClass
36 | IOResources
37 | IOResourceMatch
38 | IOKit
39 |
40 | NVHDAEnabler
41 |
42 | CFBundleIdentifier
43 | $(PRODUCT_BUNDLE_IDENTIFIER)
44 | IOClass
45 | NVHDAEnabler
46 | IOMatchCategory
47 | IOFramebuffer
48 | IOPCIClassMatch
49 | 0x03000000&0xff000000
50 | IOPCIMatch
51 | 0x000010de&0x0000ffff
52 | IOProbeScore
53 | 300000
54 | IOProviderClass
55 | IOPCIDevice
56 |
57 |
58 | NSHumanReadableCopyright
59 | Copyright © 2018 vit9696. All rights reserved.
60 | OSBundleLibraries
61 |
62 | com.apple.kpi.bsd
63 | 10.0.0
64 | com.apple.kpi.dsep
65 | 10.0.0
66 | com.apple.kpi.iokit
67 | 10.0.0
68 | com.apple.kpi.libkern
69 | 10.0.0
70 | com.apple.kpi.mach
71 | 10.0.0
72 | com.apple.kpi.unsupported
73 | 10.0.0
74 | com.apple.iokit.IOPCIFamily
75 | 1.0.0b1
76 | as.vit9696.Lilu
77 | 1.2.0
78 |
79 | OSBundleRequired
80 | Root
81 |
82 |
83 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_atom.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_atom.hpp
3 | // WhateverGreen
4 | //
5 | // Copyright © 2017 vit9696. All rights reserved.
6 | //
7 |
8 | #ifndef kern_atom_h
9 | #define kern_atom_h
10 |
11 | #include
12 |
13 | enum class AtomObjectTableType : uint8_t {
14 | DisplayPath,
15 | // This appears to be a mistake left in getAtomObjectTableForType
16 | // Instead of adding DeviceSupport table offset placed at 0
17 | // Apple adds just 0, resulting in AtomObjectTable base address + 4 bytes.
18 | // As a result we could save some time by solving one less pointer.
19 | Common,
20 | EncoderObject,
21 | ConnectorObject,
22 | RouterObject,
23 | ProtectionObject
24 | };
25 |
26 | struct AtomDisplayObjectPath {
27 | uint16_t usDeviceTag; /* supported device */
28 | uint16_t usSize; /* the size of ATOM_DISPLAY_OBJECT_PATH */
29 | uint16_t usConnObjectId; /* Connector Object ID */
30 | uint16_t usGPUObjectId; /* GPU ID */
31 | uint16_t usGraphicObjIds; /* 1st Encoder Obj source from GPU to last Graphic Obj destinate to connector. */
32 | };
33 |
34 | struct AtomConnectorObject {
35 | uint16_t usObjectID;
36 | uint16_t usSrcDstTableOffset;
37 | uint16_t usRecordOffset;
38 | uint16_t usReserved;
39 | };
40 |
41 | enum class AtomRecordType : uint8_t {
42 | Unknown = 0,
43 | I2C = 1,
44 | Max = 0xFF
45 | };
46 |
47 | struct AtomCommonRecordHeader {
48 | AtomRecordType ucRecordType;
49 | uint8_t ucRecordSize;
50 | };
51 |
52 | // Definitions taken from asic_reg/ObjectID.h
53 | enum {
54 | /* External Third Party Encoders */
55 | ENCODER_OBJECT_ID_SI170B = 0x08,
56 | ENCODER_OBJECT_ID_CH7303 = 0x09,
57 | ENCODER_OBJECT_ID_CH7301 = 0x0A,
58 | ENCODER_OBJECT_ID_INTERNAL_DVO1 = 0x0B, /* This belongs to Radeon Class Display Hardware */
59 | ENCODER_OBJECT_ID_EXTERNAL_SDVOA = 0x0C,
60 | ENCODER_OBJECT_ID_EXTERNAL_SDVOB = 0x0D,
61 | ENCODER_OBJECT_ID_TITFP513 = 0x0E,
62 | ENCODER_OBJECT_ID_INTERNAL_LVTM1 = 0x0F, /* not used for Radeon */
63 | ENCODER_OBJECT_ID_VT1623 = 0x10,
64 | ENCODER_OBJECT_ID_HDMI_SI1930 = 0x11,
65 | ENCODER_OBJECT_ID_HDMI_INTERNAL = 0x12,
66 | /* Kaleidoscope (KLDSCP) Class Display Hardware (internal) */
67 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 = 0x13,
68 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 = 0x14,
69 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 = 0x15,
70 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 = 0x16, /* Shared with CV/TV and CRT */
71 | ENCODER_OBJECT_ID_SI178 = 0X17, /* External TMDS (dual link, no HDCP.) */
72 | ENCODER_OBJECT_ID_MVPU_FPGA = 0x18, /* MVPU FPGA chip */
73 | ENCODER_OBJECT_ID_INTERNAL_DDI = 0x19,
74 | ENCODER_OBJECT_ID_VT1625 = 0x1A,
75 | ENCODER_OBJECT_ID_HDMI_SI1932 = 0x1B,
76 | ENCODER_OBJECT_ID_DP_AN9801 = 0x1C,
77 | ENCODER_OBJECT_ID_DP_DP501 = 0x1D,
78 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY = 0x1E,
79 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA = 0x1F,
80 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 = 0x20,
81 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 = 0x21,
82 | ENCODER_OBJECT_ID_ALMOND = 0x22,
83 | ENCODER_OBJECT_ID_NUTMEG = 0x22,
84 | ENCODER_OBJECT_ID_TRAVIS = 0x23,
85 | ENCODER_OBJECT_ID_INTERNAL_VCE = 0x24,
86 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 = 0x25,
87 | ENCODER_OBJECT_ID_INTERNAL_AMCLK = 0x27
88 | };
89 |
90 | enum {
91 | CONNECTOR_OBJECT_ID_NONE = 0x00,
92 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I = 0x01,
93 | CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I = 0x02,
94 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D = 0x03,
95 | CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D = 0x04,
96 | CONNECTOR_OBJECT_ID_VGA = 0x05,
97 | CONNECTOR_OBJECT_ID_COMPOSITE = 0x06,
98 | CONNECTOR_OBJECT_ID_SVIDEO = 0x07,
99 | CONNECTOR_OBJECT_ID_YPbPr = 0x08,
100 | CONNECTOR_OBJECT_ID_D_CONNECTOR = 0x09,
101 | CONNECTOR_OBJECT_ID_9PIN_DIN = 0x0A, /* Supports both CV & TV */
102 | CONNECTOR_OBJECT_ID_SCART = 0x0B,
103 | CONNECTOR_OBJECT_ID_HDMI_TYPE_A = 0x0C,
104 | CONNECTOR_OBJECT_ID_HDMI_TYPE_B = 0x0D,
105 | CONNECTOR_OBJECT_ID_LVDS = 0x0E,
106 | CONNECTOR_OBJECT_ID_7PIN_DIN = 0x0F,
107 | CONNECTOR_OBJECT_ID_PCIE_CONNECTOR = 0x10,
108 | CONNECTOR_OBJECT_ID_CROSSFIRE = 0x11,
109 | CONNECTOR_OBJECT_ID_HARDCODE_DVI = 0x12,
110 | CONNECTOR_OBJECT_ID_DISPLAYPORT = 0x13,
111 | CONNECTOR_OBJECT_ID_eDP = 0x14,
112 | CONNECTOR_OBJECT_ID_MXM = 0x15,
113 | CONNECTOR_OBJECT_ID_LVDS_eDP = 0x16
114 | };
115 |
116 | enum {
117 | GRAPH_OBJECT_TYPE_NONE = 0x0,
118 | GRAPH_OBJECT_TYPE_GPU = 0x1,
119 | GRAPH_OBJECT_TYPE_ENCODER = 0x2,
120 | GRAPH_OBJECT_TYPE_CONNECTOR = 0x3,
121 | GRAPH_OBJECT_TYPE_ROUTER = 0x4
122 | };
123 |
124 | static constexpr uint16_t OBJECT_ID_MASK = 0x00FF;
125 | static constexpr uint16_t ENUM_ID_MASK = 0x0700;
126 | static constexpr uint16_t RESERVED1_ID_MASK = 0x0800;
127 | static constexpr uint16_t OBJECT_TYPE_MASK = 0x7000;
128 | static constexpr uint16_t RESERVED2_ID_MASK = 0x8000;
129 | static constexpr uint16_t OBJECT_ID_SHIFT = 0x00;
130 | static constexpr uint16_t ENUM_ID_SHIFT = 0x08;
131 | static constexpr uint16_t OBJECT_TYPE_SHIFT = 0x0C;
132 |
133 | /**
134 | * Checks if object is encoder
135 | *
136 | * @param objid object id
137 | *
138 | * @return true one success
139 | */
140 | inline bool isEncoder(uint16_t objid) {
141 | return ((objid & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT) == GRAPH_OBJECT_TYPE_ENCODER;
142 | }
143 |
144 | /**
145 | * Retrieve connector
146 | *
147 | * @param objid object id
148 | *
149 | * @return connector id
150 | */
151 | inline uint8_t getConnectorID(uint16_t objid) {
152 | return static_cast(objid);
153 | }
154 | /**
155 | * Retrieve sense ID
156 | *
157 | * @param record pointer to atom records
158 | *
159 | * @return sense id or 0
160 | */
161 | inline uint8_t getSenseID(uint8_t *record) {
162 | // Partially reversed from AtiAtomBiosDceInterface::parseSenseId
163 | if (record) {
164 | while (true) {
165 | auto h = reinterpret_cast(record);
166 | if (h->ucRecordType == AtomRecordType::I2C) {
167 | if (record[2] > 0)
168 | return (record[2] & 0xF) + 1;
169 | return 0;
170 | } else if (h->ucRecordType == AtomRecordType::Max) {
171 | return 0;
172 | }
173 | record += h->ucRecordSize;
174 | }
175 | }
176 |
177 | return 0;
178 | }
179 |
180 | /**
181 | * Retrieve transmitter and encoder
182 | *
183 | * @param usGraphicObjIds encoder objcect id
184 | * @param txmit reference to transmitter var
185 | * @param enc reference to encoder var
186 | *
187 | * @return true on success
188 | */
189 | inline bool getTxEnc(uint16_t usGraphicObjIds, uint8_t &txmit, uint8_t &enc) {
190 | bool extra = ((usGraphicObjIds & ENUM_ID_MASK) >> ENUM_ID_SHIFT) > 1;
191 | uint8_t encoder = static_cast(usGraphicObjIds);
192 | // This is partially taken from AtiAtomBiosDce60::getPropertiesForConnectorObject and similar functions.
193 | if (encoder == ENCODER_OBJECT_ID_INTERNAL_UNIPHY) {
194 | txmit = extra ? 0x20 : 0x10;
195 | enc = extra;
196 | } else if (encoder == ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 ||
197 | encoder == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) {
198 | txmit = extra ? 0x21 : 0x11;
199 | enc = 2 + extra;
200 | // Apple also has ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA here
201 | } else if (encoder == ENCODER_OBJECT_ID_INTERNAL_UNIPHY2) {
202 | txmit = extra ? 0x22 : 0x12;
203 | enc = 4 + extra;
204 | } else {
205 | DBGLOG("atom", "getTxEnc found unsupported encoder %02X objid %04X", encoder, usGraphicObjIds);
206 | return false;
207 | }
208 |
209 | return true;
210 | }
211 |
212 | #endif /* kern_atom_h */
213 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_cdf.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_cdf.cpp
3 | // WhateverGreen
4 | //
5 | // Copyright © 2018 vit9696. All rights reserved.
6 | //
7 |
8 | #include "kern_cdf.hpp"
9 |
10 | #include
11 | #include
12 |
13 | // NVDAGK100Hal.kext - system built-in, for Kepler
14 | static const char *pathGKHal[] = {
15 | "/System/Library/Extensions/NVDAGK100Hal.kext/Contents/MacOS/NVDAGK100Hal"
16 | };
17 |
18 | // NVDAGK100HalWeb.kext - from web driver, for Kepler
19 | static const char *pathGKWeb[] = {
20 | "/Library/Extensions/NVDAGK100HalWeb.kext/Contents/MacOS/NVDAGK100HalWeb",
21 | "/System/Library/Extensions/NVDAGK100HalWeb.kext/Contents/MacOS/NVDAGK100HalWeb"
22 | };
23 |
24 | // NVDAGM100HalWeb.kext - from web driver, for Maxwell
25 | static const char *pathGMWeb[] = {
26 | "/Library/Extensions/NVDAGM100HalWeb.kext/Contents/MacOS/NVDAGM100HalWeb",
27 | "/System/Library/Extensions/NVDAGM100HalWeb.kext/Contents/MacOS/NVDAGM100HalWeb"
28 | };
29 |
30 | // NVDAGP100HalWeb.kext - from web driver, for Pascal
31 | static const char *pathGPWeb[] = {
32 | "/Library/Extensions/NVDAGP100HalWeb.kext/Contents/MacOS/NVDAGP100HalWeb",
33 | "/System/Library/Extensions/NVDAGP100HalWeb.kext/Contents/MacOS/NVDAGP100HalWeb"
34 | };
35 |
36 | static KernelPatcher::KextInfo kextList[] {
37 | { "com.apple.nvidia.driver.NVDAGK100Hal", pathGKHal, arrsize(pathGKHal), {}, {}, KernelPatcher::KextInfo::Unloaded },
38 | { "com.nvidia.web.NVDAGK100HalWeb", pathGKWeb, arrsize(pathGKWeb), {}, {}, KernelPatcher::KextInfo::Unloaded },
39 | { "com.nvidia.web.NVDAGM100HalWeb", pathGMWeb, arrsize(pathGMWeb), {}, {}, KernelPatcher::KextInfo::Unloaded },
40 | { "com.nvidia.web.NVDAGP100HalWeb", pathGPWeb, arrsize(pathGPWeb), {}, {}, KernelPatcher::KextInfo::Unloaded },
41 | };
42 |
43 | enum : size_t {
44 | KextGK100HalSys,
45 | KextGK100HalWeb,
46 | KextGM100HalWeb,
47 | KextGP100HalWeb
48 | };
49 |
50 | // target framework for 10.10.x and 10.11.x
51 | static const char *binaryIOKitFramework = "/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit";
52 | // target framework as of 10.12.x
53 | static const char *binaryCoreDisplayFramework = "/System/Library/Frameworks/CoreDisplay.framework/Versions/A/CoreDisplay";
54 | // accompanied process for 10.10.x or 10.11.x
55 | static const char *procWindowServerOld = "/System/Library/Frameworks/CoreGraphics.framework/Versions/A/Resources/WindowServer";
56 | static uint32_t procWindowServerOldLen = sizeof("/System/Library/Frameworks/CoreGraphics.framework/Versions/A/Resources/WindowServer") - 1;
57 | // accompanied process for 10.12.x
58 | static const char *procWindowServerNew = "/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/Resources/WindowServer";
59 | static uint32_t procWindowServerNewLen = sizeof("/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/Resources/WindowServer") - 1;
60 |
61 | enum : uint32_t {
62 | SectionYosEC = 1,
63 | SectionSieHS = 2,
64 | SectionHS1034 = 3
65 | };
66 |
67 | // Patches
68 | //
69 | // for NVDAGK100Hal and NVDAGK100HalWeb
70 | //
71 | // Reference:
72 | // https://github.com/Floris497/mac-pixel-clock-patch-V2/blob/master/NVIDIA-patcher.command
73 | //
74 | static const uint8_t gk100Find[] = { 0x88, 0x84, 0x02, 0x00 };
75 | static const uint8_t gk100Repl[] = { 0x80, 0x1A, 0x06, 0x00 };
76 | //
77 | // for NVDAGM100HalWeb and NVDAGP100HalWeb
78 | //
79 | // Reference:
80 | // https://github.com/Floris497/mac-pixel-clock-patch-V2/blob/master/NVIDIA-WEB-MAXWELL-patcher.command
81 | //
82 | static const uint8_t gmp100Find[] = { 0x88, 0x84, 0x02, 0x00 };
83 | static const uint8_t gmp100Repl[] = { 0x40, 0x42, 0x0F, 0x00 };
84 | //
85 | // for frameworks
86 | //
87 | // Reference:
88 | // https://github.com/Floris497/mac-pixel-clock-patch-V2/blob/master/CoreDisplay-patcher.command
89 | //
90 | // Modified by PMheart (jmpq adress optimisations)
91 | //
92 | // Patches int CheckTimingWithRange(IOFBConnectRef, IODisplayTimingRange *, IODetailedTimingInformation *)
93 | // to always return 0 and thus effectively allow the use of any resolution regardless of connection
94 | // capability. May cause blackscreen with several configurations.
95 | static const uint8_t frameworkOldFind[] {
96 | 0xB8, 0x01, 0x00, 0x00, 0x00, // mov eax, 0x1
97 | 0xF6, 0xC1, 0x01, // test cl, 0x1
98 | 0x0F, 0x85 // jne "somewhere" ; Don't care for the exact offset!
99 | };
100 |
101 | static const uint8_t frameworkOldRepl[] {
102 | 0x33, 0xC0, // xor eax, eax ; 0
103 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nop (7x) ; placeholders
104 | 0xE9 // jmp "somewhere" ; Don't care for the exact offset!
105 | };
106 |
107 | // 10.13.4+
108 | static const uint8_t frameworkNewFind[] {
109 | 0xBB, 0x01, 0x00, 0x00, 0x00, // mov ebx, 0x1
110 | 0xA8, 0x01, // test al, 0x1
111 | 0x0F, 0x85 // jne
112 | };
113 |
114 | static const uint8_t frameworkNewRepl[] {
115 | 0x31, 0xDB, // xor ebx, ebx
116 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nop (6x)
117 | 0xE9 // jmp
118 | };
119 |
120 | static UserPatcher::BinaryModPatch frameworkPatchOld {
121 | CPU_TYPE_X86_64,
122 | 0,
123 | frameworkOldFind,
124 | frameworkOldRepl,
125 | arrsize(frameworkOldFind),
126 | 0, // skip = 0 -> replace all occurrences
127 | 1, // count = 1 -> 1 set of hex inside the target binaries
128 | UserPatcher::FileSegment::SegmentTextText,
129 | SectionHS1034 // 10.10.x till 10.13.3 (all universal)
130 | };
131 |
132 | static UserPatcher::BinaryModPatch frameworkPatchNew {
133 | CPU_TYPE_X86_64,
134 | 0,
135 | frameworkNewFind,
136 | frameworkNewRepl,
137 | arrsize(frameworkNewFind),
138 | 0, // skip = 0 -> replace all occurrences
139 | 1, // count = 1 -> 1 set of hex inside the target binaries
140 | UserPatcher::FileSegment::SegmentTextText,
141 | SectionHS1034 // 10.13.4+
142 | };
143 |
144 | // 10.10.x and 10.11.x
145 | static UserPatcher::BinaryModInfo binaryModYosEC { binaryIOKitFramework, &frameworkPatchOld, 1 };
146 | // 10.12.x and 10.13.0-10.13.3
147 | static UserPatcher::BinaryModInfo binaryModSieHS { binaryCoreDisplayFramework, &frameworkPatchOld, 1 };
148 | // 10.13.4+
149 | static UserPatcher::BinaryModInfo binaryModHS1034 { binaryCoreDisplayFramework, &frameworkPatchNew, 1 };
150 |
151 | // 10.10.x and 10.11.x
152 | static UserPatcher::ProcInfo procInfoYosEC { procWindowServerOld, procWindowServerOldLen, SectionYosEC };
153 | // 10.12.x and 10.13.x
154 | static UserPatcher::ProcInfo procInfoSieHS { procWindowServerNew, procWindowServerNewLen, SectionSieHS };
155 |
156 | CDF *CDF::callbackCDF;
157 |
158 | void CDF::init() {
159 | callbackCDF = this;
160 | lilu.onKextLoadForce(kextList, arrsize(kextList));
161 |
162 | // nothing should be applied when -cdfoff is passed
163 | if (!checkKernelArgument("-cdfoff")) {
164 | if (getKernelVersion() == KernelVersion::Yosemite || getKernelVersion() == KernelVersion::ElCapitan) {
165 | // 10.10, 10.11
166 | currentProcInfo = &procInfoYosEC;
167 | currentModInfo = &binaryModYosEC;
168 | } else if (getKernelVersion() == KernelVersion::Sierra || (getKernelVersion() == KernelVersion::HighSierra && getKernelMinorVersion() < 5)) {
169 | // 10.12, 10.13.0-10.13.3
170 | currentProcInfo = &procInfoSieHS;
171 | currentModInfo = &binaryModSieHS;
172 | } else if ((getKernelVersion() == KernelVersion::HighSierra && getKernelMinorVersion() >= 5)
173 | || getKernelVersion() >= KernelVersion::Mojave) {
174 | // the patch is indeed for 10.13.4+, 10.14.x,
175 | // and assuming identical one for 10.15+.
176 | currentProcInfo = &procInfoSieHS;
177 | currentModInfo = &binaryModHS1034;
178 | }
179 | }
180 |
181 | if (currentProcInfo && currentModInfo)
182 | lilu.onProcLoadForce(currentProcInfo, 1, nullptr, nullptr, currentModInfo, 1);
183 | }
184 |
185 | void CDF::deinit() {
186 |
187 | }
188 |
189 | void CDF::processKernel(KernelPatcher &patcher, DeviceInfo *info) {
190 | // -cdfon -> force enable
191 | // -cdfoff -> force disable
192 | // enable-hdmi20 -> enable nvidia/intel
193 | disableHDMI20 = checkKernelArgument("-cdfoff");
194 |
195 | bool patchNVIDIA = false;
196 | bool patchCommon = false;
197 |
198 | if (!disableHDMI20) {
199 | if (checkKernelArgument("-cdfon")) {
200 | patchNVIDIA = patchCommon = true;
201 | } else {
202 | for (size_t i = 0; i < info->videoExternal.size(); i++) {
203 | if (info->videoExternal[i].vendor == WIOKit::VendorID::NVIDIA)
204 | patchNVIDIA |= info->videoExternal[i].video->getProperty("enable-hdmi20") != nullptr;
205 | }
206 |
207 | if (patchNVIDIA || (info->videoBuiltin && info->videoBuiltin->getProperty("enable-hdmi20")))
208 | patchCommon = true;
209 | }
210 | }
211 |
212 | if (!patchNVIDIA) {
213 | for (size_t i = 0; i < arrsize(kextList); i++)
214 | kextList[i].switchOff();
215 | disableHDMI20 = true;
216 | }
217 |
218 | if (!patchCommon && currentProcInfo && currentModInfo) {
219 | currentProcInfo->section = UserPatcher::ProcInfo::SectionDisabled;
220 | for (size_t i = 0; i < currentModInfo->count; i++)
221 | currentModInfo->patches[i].section = UserPatcher::ProcInfo::SectionDisabled;
222 | }
223 | }
224 |
225 | bool CDF::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
226 | if (disableHDMI20)
227 | return false;
228 |
229 | if (kextList[KextGK100HalSys].loadIndex == index) {
230 | KernelPatcher::LookupPatch patch {&kextList[KextGK100HalSys], gk100Find, gk100Repl, sizeof(gk100Find), 1};
231 | patcher.applyLookupPatch(&patch);
232 | if (patcher.getError() != KernelPatcher::Error::NoError) {
233 | SYSLOG("cdf", "failed to apply gk100 patch %d", patcher.getError());
234 | patcher.clearError();
235 | }
236 | return true;
237 | }
238 |
239 | if (kextList[KextGK100HalWeb].loadIndex == index) {
240 | KernelPatcher::LookupPatch patch {&kextList[KextGK100HalWeb], gk100Find, gk100Repl, sizeof(gk100Find), 1};
241 | patcher.applyLookupPatch(&patch);
242 | if (patcher.getError() != KernelPatcher::Error::NoError) {
243 | SYSLOG("cdf", "failed to apply gk100 web patch %d", patcher.getError());
244 | patcher.clearError();
245 | }
246 | return true;
247 | }
248 |
249 | if (kextList[KextGM100HalWeb].loadIndex == index) {
250 | KernelPatcher::LookupPatch patch {&kextList[KextGM100HalWeb], gmp100Find, gmp100Repl, sizeof(gmp100Find), 1};
251 | patcher.applyLookupPatch(&patch);
252 | if (patcher.getError() != KernelPatcher::Error::NoError) {
253 | SYSLOG("cdf", "failed to apply gm100 web patch %d", patcher.getError());
254 | patcher.clearError();
255 | }
256 | return true;
257 | }
258 |
259 | if (kextList[KextGP100HalWeb].loadIndex == index) {
260 | KernelPatcher::LookupPatch patch {&kextList[KextGP100HalWeb], gmp100Find, gmp100Repl, sizeof(gmp100Find), 1};
261 | patcher.applyLookupPatch(&patch);
262 | if (patcher.getError() != KernelPatcher::Error::NoError) {
263 | SYSLOG("cdf", "failed to apply gp100 web patch %d", patcher.getError());
264 | patcher.clearError();
265 | }
266 | return true;
267 | }
268 |
269 | return false;
270 | }
271 |
272 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_cdf.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_cdf.hpp
3 | // WhateverGreen
4 | //
5 | // Copyright © 2018 vit9696. All rights reserved.
6 | //
7 |
8 | #ifndef kern_cdf_hpp
9 | #define kern_cdf_hpp
10 |
11 | #include
12 | #include
13 | #include
14 |
15 | class CDF {
16 | public:
17 | void init();
18 | void deinit();
19 |
20 | /**
21 | * Property patching routine
22 | *
23 | * @param patcher KernelPatcher instance
24 | * @param info device info
25 | */
26 | void processKernel(KernelPatcher &patcher, DeviceInfo *info);
27 |
28 | /**
29 | * Patch kext if needed and prepare other patches
30 | *
31 | * @param patcher KernelPatcher instance
32 | * @param index kinfo handle
33 | * @param address kinfo load address
34 | * @param size kinfo memory size
35 | *
36 | * @return true if patched anything
37 | */
38 | bool processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size);
39 |
40 | private:
41 | /**
42 | * Private self instance for callbacks
43 | */
44 | static CDF *callbackCDF;
45 |
46 | /**
47 | * Current proc info containing the right path to WindowServer
48 | */
49 | UserPatcher::ProcInfo *currentProcInfo {nullptr};
50 |
51 | /**
52 | * Current binary modification containing the right framework mod
53 | */
54 | UserPatcher::BinaryModInfo *currentModInfo {nullptr};
55 |
56 | /**
57 | * Disable the patches based on -cdfoff boot-arg
58 | */
59 | bool disableHDMI20 = false;
60 | };
61 |
62 | #endif /* kern_cdf_hpp */
63 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_con.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_con.hpp
3 | // WhateverGreen
4 | //
5 | // Copyright © 2017 vit9696. All rights reserved.
6 | //
7 |
8 | #ifndef kern_con_hpp
9 | #define kern_con_hpp
10 |
11 | #include
12 | #include
13 |
14 | namespace RADConnectors {
15 |
16 | /**
17 | * Connectors from AMDSupport before 10.12
18 | */
19 | struct LegacyConnector {
20 | uint32_t type;
21 | uint32_t flags;
22 | uint16_t features;
23 | uint16_t priority;
24 | uint8_t transmitter;
25 | uint8_t encoder;
26 | uint8_t hotplug;
27 | uint8_t sense;
28 | };
29 |
30 | /**
31 | * Connectors from AMDSupport since 10.12
32 | */
33 | struct ModernConnector {
34 | uint32_t type;
35 | uint32_t flags;
36 | uint16_t features;
37 | uint16_t priority;
38 | uint32_t reserved1;
39 | uint8_t transmitter;
40 | uint8_t encoder;
41 | uint8_t hotplug;
42 | uint8_t sense;
43 | uint32_t reserved2;
44 | };
45 |
46 | /**
47 | * Internal atom connector struct since 10.13
48 | */
49 | struct AtomConnectorInfo {
50 | uint16_t *atomObject;
51 | uint16_t usConnObjectId;
52 | uint16_t usGraphicObjIds;
53 | uint8_t *hpdRecord;
54 | uint8_t *i2cRecord;
55 | };
56 |
57 | /**
58 | * Opaque connector type for simplicity
59 | */
60 | union Connector {
61 | LegacyConnector legacy;
62 | ModernConnector modern;
63 |
64 | static_assert(sizeof(LegacyConnector) == 16, "LegacyConnector has wrong size");
65 | static_assert(sizeof(ModernConnector) == 24, "ModernConnector has wrong size");
66 |
67 | /**
68 | * Assigns connector from one to another
69 | *
70 | * @param out destination connector
71 | * @param in source connector
72 | */
73 | template
74 | static inline void assign(T &out, const Y &in) {
75 | memset(&out, 0, sizeof(T));
76 | out.type = in.type;
77 | out.flags = in.flags;
78 | out.features = in.features;
79 | out.priority = in.priority;
80 | out.transmitter = in.transmitter;
81 | out.encoder = in.encoder;
82 | out.hotplug = in.hotplug;
83 | out.sense = in.sense;
84 | }
85 | };
86 |
87 | /**
88 | * Connector types available in the drivers
89 | */
90 | enum ConnectorType {
91 | ConnectorLVDS = 0x2,
92 | ConnectorDigitalDVI = 0x4,
93 | ConnectorSVID = 0x8,
94 | ConnectorVGA = 0x10,
95 | ConnectorDP = 0x400,
96 | ConnectorHDMI = 0x800,
97 | ConnectorAnalogDVI = 0x2000
98 | };
99 |
100 | /**
101 | * Prints connector type
102 | *
103 | * @param type connector type
104 | */
105 | inline const char *printType(uint32_t type) {
106 | switch (type) {
107 | case ConnectorLVDS:
108 | return "LVDS";
109 | case ConnectorDigitalDVI:
110 | return "DVI ";
111 | case ConnectorSVID:
112 | return "SVID";
113 | case ConnectorVGA:
114 | return "VGA ";
115 | case ConnectorDP:
116 | return "DP ";
117 | case ConnectorHDMI:
118 | return "HDMI";
119 | case ConnectorAnalogDVI:
120 | return "ADVI";
121 | default:
122 | return "UNKN";
123 | }
124 | }
125 |
126 | /**
127 | * Prints connector
128 | *
129 | * @param out out buffer
130 | * @param connector typed connector
131 | *
132 | * @return out
133 | */
134 | template
135 | inline char *printConnector(char (&out)[N], T &connector) {
136 | snprintf(out, N, "type %08X (%s) flags %08X feat %04X pri %04X txmit %02X enc %02X hotplug %02X sense %02X", connector.type, printType(connector.type),
137 | connector.flags, connector.features, connector.priority, connector.transmitter, connector.encoder, connector.hotplug, connector.sense);
138 | return out;
139 | }
140 |
141 | /**
142 | * Is modern system
143 | *
144 | * @return true if modern connectors are used
145 | */
146 | inline bool modern() {
147 | return getKernelVersion() >= KernelVersion::Sierra;
148 | }
149 |
150 | /**
151 | * Prints connectors
152 | *
153 | * @param con pointer to an array of legacy or modern connectors (depends on the kernel version)
154 | * @param num number of connectors in con
155 | */
156 | inline void print(Connector *con, uint8_t num) {
157 | #ifdef DEBUG
158 | for (uint8_t i = 0; con && i < num; i++) {
159 | char tmp[192];
160 | DBGLOG("con", "%u is %s", i, modern() ?
161 | printConnector(tmp, (&con->modern)[i]) : printConnector(tmp, (&con->legacy)[i]));
162 | }
163 | #endif
164 | }
165 |
166 | /**
167 | * Sanity check connector size
168 | *
169 | * @param size buffer size in bytes
170 | * @param num number of connectors
171 | *
172 | * @return true if connectors are in either legacy or modern format
173 | */
174 | inline bool valid(uint32_t size, uint8_t num) {
175 | return (size % sizeof(ModernConnector) == 0 && size / sizeof(ModernConnector) == num) ||
176 | (size % sizeof(LegacyConnector) == 0 && size / sizeof(LegacyConnector) == num);
177 | }
178 |
179 | /**
180 | * Copy new connectors
181 | *
182 | * @param out destination connectors
183 | * @param num number of copied connectors
184 | * @param in source connectors
185 | * @param size size of source connectors
186 | */
187 | inline void copy(RADConnectors::Connector *out, uint8_t num, const RADConnectors::Connector *in, uint32_t size) {
188 | bool outModern = modern();
189 | bool inModern = size % sizeof(ModernConnector) == 0 && size / sizeof(ModernConnector) == num;
190 |
191 | for (uint8_t i = 0; i < num; i++) {
192 | if (outModern) {
193 | if (inModern)
194 | Connector::assign((&out->modern)[i], (&in->modern)[i]);
195 | else
196 | Connector::assign((&out->modern)[i], (&in->legacy)[i]);
197 | } else {
198 | if (inModern)
199 | Connector::assign((&out->legacy)[i], (&in->modern)[i]);
200 | else
201 | Connector::assign((&out->legacy)[i], (&in->legacy)[i]);
202 | }
203 |
204 | }
205 | }
206 | };
207 |
208 | #endif /* kern_con_hpp */
209 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_guc.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_guc.hpp
3 | // WhateverGreen
4 | //
5 | // Copyright © 2018 vit9696. All rights reserved.
6 | //
7 |
8 | #ifndef kern_guc_hpp
9 | #define kern_guc_hpp
10 |
11 | #include
12 |
13 | static constexpr size_t GuCFirmwareSignatureSize = 256;
14 |
15 | extern const uint8_t *GuCFirmwareSKL;
16 | extern const uint8_t *GuCFirmwareSKLSignature;
17 | extern const size_t GuCFirmwareSKLSize;
18 |
19 | extern const uint8_t *GuCFirmwareKBL;
20 | extern const uint8_t *GuCFirmwareKBLSignature;
21 | extern const size_t GuCFirmwareKBLSize;
22 |
23 | #endif /* kern_guc_hpp */
24 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_igfx_backlight.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_igfx_backlight.hpp
3 | // WhateverGreen
4 | //
5 | // Created by FireWolf on 7/29/21.
6 | // Copyright © 2021 vit9696. All rights reserved.
7 | //
8 |
9 | #ifndef kern_igfx_backlight_hpp
10 | #define kern_igfx_backlight_hpp
11 |
12 | #include
13 | #include "kern_util.hpp"
14 |
15 | /**
16 | * Backlight registers
17 | */
18 | static constexpr uint32_t BLC_PWM_CPU_CTL = 0x48254;
19 | static constexpr uint32_t BXT_BLC_PWM_CTL1 = 0xC8250;
20 | static constexpr uint32_t BXT_BLC_PWM_FREQ1 = 0xC8254;
21 | static constexpr uint32_t BXT_BLC_PWM_DUTY1 = 0xC8258;
22 |
23 | static constexpr uint32_t SFUSE_STRAP = 0xC2014;
24 | static constexpr uint32_t SFUSE_STRAP_RAW_FREQUENCY = 1 << 8;
25 |
26 | /**
27 | * Ice Lake freq
28 | * Copied from `AppleIntelFramebufferController::start()` function
29 | */
30 | static constexpr uint32_t ICL_FREQ_NORMAL = 17777;
31 | static constexpr uint32_t ICL_FREQ_RAW = 22222;
32 |
33 | /**
34 | * Represents a single brightness adjustment request
35 | */
36 | struct BrightnessRequest {
37 | /**
38 | * The framebuffer controller
39 | */
40 | void *controller {nullptr};
41 |
42 | /**
43 | * The register address
44 | */
45 | uint32_t address {0};
46 |
47 | /**
48 | * The target register value
49 | */
50 | uint32_t target {0};
51 |
52 | /**
53 | * Specify the portion of bits in the register value that represent the brightness level
54 | */
55 | uint32_t mask {0};
56 |
57 | /**
58 | * The request ID to check if the request was changed
59 | */
60 | uint32_t id {0};
61 |
62 | /**
63 | * Create an empty request
64 | */
65 | BrightnessRequest() = default;
66 |
67 | /**
68 | * Create a brightness request
69 | */
70 | BrightnessRequest(uint32_t id, void *controller, uint32_t address, uint32_t target, uint32_t mask = 0xFFFFFFFF) :
71 | id(id), controller(controller), address(address), target(target), mask(mask) {}
72 |
73 | /**
74 | * Get the current brightness level
75 | *
76 | * @param current The current register value
77 | * @return The current brightness level.
78 | */
79 | inline uint32_t getCurrentBrightness(uint32_t current) {
80 | return current & mask;
81 | }
82 |
83 | /**
84 | * Get the target brightness level
85 | *
86 | * @return The target brightness level.
87 | */
88 | inline uint32_t getTargetBrightness() {
89 | return target & mask;
90 | }
91 |
92 | /**
93 | * Get the target register value from the given brightness level
94 | *
95 | * @param brightness The brightness level
96 | * @return The corresponding register value
97 | */
98 | inline uint32_t getTargetRegisterValue(uint32_t brightness) {
99 | return brightness | (target & ~mask);
100 | }
101 | };
102 |
103 | /**
104 | * An event source that adjusts the brightness smoothly
105 | */
106 | class BrightnessRequestEventSource: public IOEventSource {
107 | /**
108 | * Constructors & Destructors
109 | */
110 | OSDeclareDefaultStructors(BrightnessRequestEventSource);
111 |
112 | using super = IOEventSource;
113 |
114 | /**
115 | * Check whether a brightness adjustment request is pending and if so process the request on the workloop
116 | *
117 | * @return `true` if the work loop should invoke this function again.
118 | * i.e., One or more requests are pending after the workloop has processed the current one.
119 | */
120 | bool checkForWork() override;
121 |
122 | public:
123 | /**
124 | * Create an event source
125 | *
126 | * @param owner The owner of the event source
127 | * @return A non-null event source on success, `nullptr` otherwise.
128 | */
129 | static BrightnessRequestEventSource *create(OSObject *owner);
130 | };
131 |
132 | #endif /* kern_igfx_backlight_hpp */
133 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_igfx_i2c_aux.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_igfx_i2c_aux.cpp
3 | // WhateverGreen
4 | //
5 | // Created by FireWolf on 9/21/20.
6 | // Copyright © 2020 vit9696. All rights reserved.
7 | //
8 |
9 | #include
10 | #include "kern_igfx.hpp"
11 |
12 | void IGFX::AdvancedI2COverAUXSupport::init() {
13 | // We only need to patch the framebuffer driver
14 | requiresPatchingGraphics = false;
15 | requiresPatchingFramebuffer = true;
16 | }
17 |
18 | void IGFX::AdvancedI2COverAUXSupport::processKernel(KernelPatcher &patcher, DeviceInfo *info) {
19 | // Enable the advanced I2C-over-AUX support if LSPCON is enabled
20 | enabled = callbackIGFX->modLSPCONDriverSupport.enabled;
21 |
22 | // Or if verbose output in transactions is enabled
23 | if (checkKernelArgument("-igfxi2cdbg")) {
24 | enabled = true;
25 | verbose = true;
26 | }
27 | }
28 |
29 | void IGFX::AdvancedI2COverAUXSupport::processFramebufferKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
30 | KernelPatcher::RouteRequest requests[] = {
31 | {
32 | "__ZN31AppleIntelFramebufferController14ReadI2COverAUXEP21AppleIntelFramebufferP21AppleIntelDisplayPathjtPhbh",
33 | wrapReadI2COverAUX,
34 | reinterpret_cast(orgReadI2COverAUX)
35 | },
36 | {
37 | "__ZN31AppleIntelFramebufferController15WriteI2COverAUXEP21AppleIntelFramebufferP21AppleIntelDisplayPathjtPhb",
38 | wrapWriteI2COverAUX,
39 | reinterpret_cast(orgWriteI2COverAUX)
40 | }
41 | };
42 |
43 | if (patcher.routeMultiple(index, requests, address, size))
44 | DBGLOG("igfx", "I2C: Functions have been routed successfully");
45 | else
46 | SYSLOG("igfx", "I2C: Failed to route functions.");
47 | }
48 |
49 | IOReturn IGFX::AdvancedI2COverAUXSupport::wrapReadI2COverAUX(void *that, IORegistryEntry *framebuffer, void *displayPath, uint32_t address, uint16_t length, uint8_t *buffer, bool intermediate, uint8_t flags) {
50 | if (callbackIGFX->modAdvancedI2COverAUXSupport.verbose) {
51 | uint32_t index = 0xFF;
52 | AppleIntelFramebufferExplorer::getIndex(framebuffer, index);
53 | DBGLOG("igfx", "I2C: ReadI2COverAUX() called. FB%d: Addr = 0x%02x; Len = %02d; MOT = %d; Flags = %d.",
54 | index, address, length, intermediate, flags);
55 | IOReturn retVal = callbackIGFX->modAdvancedI2COverAUXSupport.orgReadI2COverAUX(that, framebuffer, displayPath, address, length, buffer, intermediate, flags);
56 | DBGLOG("igfx", "I2C: ReadI2COverAUX() returns 0x%x.", retVal);
57 | return retVal;
58 | } else {
59 | return callbackIGFX->modAdvancedI2COverAUXSupport.orgReadI2COverAUX(that, framebuffer, displayPath, address, length, buffer, intermediate, flags);
60 | }
61 | }
62 |
63 | IOReturn IGFX::AdvancedI2COverAUXSupport::wrapWriteI2COverAUX(void *that, IORegistryEntry *framebuffer, void *displayPath, uint32_t address, uint16_t length, uint8_t *buffer, bool intermediate) {
64 | if (callbackIGFX->modAdvancedI2COverAUXSupport.verbose) {
65 | uint32_t index = 0xFF;
66 | AppleIntelFramebufferExplorer::getIndex(framebuffer, index);
67 | DBGLOG("igfx", "I2C: WriteI2COverAUX() called. FB%d: Addr = 0x%02x; Len = %02d; MOT = %d; Flags = 0.",
68 | index, address, length, intermediate);
69 | IOReturn retVal = callbackIGFX->modAdvancedI2COverAUXSupport.orgWriteI2COverAUX(that, framebuffer, displayPath, address, length, buffer, intermediate);
70 | DBGLOG("igfx", "I2C: WriteI2COverAUX() returns 0x%x.", retVal);
71 | return retVal;
72 | } else {
73 | return callbackIGFX->modAdvancedI2COverAUXSupport.orgWriteI2COverAUX(that, framebuffer, displayPath, address, length, buffer, intermediate);
74 | }
75 | }
76 |
77 | IOReturn IGFX::AdvancedI2COverAUXSupport::advSeekI2COverAUX(void *that, IORegistryEntry *framebuffer, void *displayPath, uint32_t address, uint32_t offset, uint8_t flags) {
78 | // No need to check the given `address` and `offset`
79 | // if they are invalid, the underlying RunAUXCommand() will return an error
80 | // First start the transaction by performing an empty write
81 | IOReturn retVal = wrapWriteI2COverAUX(that, framebuffer, displayPath, address, 0, nullptr, true);
82 |
83 | // Guard: Check the START transaction
84 | if (retVal != kIOReturnSuccess) {
85 | SYSLOG("igfx", "I2C: AdvSeekI2COverAUX() Error: Failed to start the I2C transaction. Return value = 0x%x.\n", retVal);
86 | return retVal;
87 | }
88 |
89 | // Write a single byte to the given I2C slave
90 | // and set the Middle-of-Transaction bit to 1
91 | return wrapWriteI2COverAUX(that, framebuffer, displayPath, address, 1, reinterpret_cast(&offset), true);
92 | }
93 |
94 | IOReturn IGFX::AdvancedI2COverAUXSupport::advReadI2COverAUX(void *that, IORegistryEntry *framebuffer, void *displayPath, uint32_t address, uint32_t offset, uint16_t length, uint8_t *buffer, uint8_t flags) {
95 | // Guard: Check the buffer length
96 | if (length == 0) {
97 | SYSLOG("igfx", "I2C: AdvReadI2COverAUX() Error: Buffer length must be non-zero.");
98 | return kIOReturnInvalid;
99 | }
100 |
101 | // Guard: Check the buffer
102 | if (buffer == nullptr) {
103 | SYSLOG("igfx", "I2C: AdvReadI2COverAUX() Error: Buffer cannot be NULL.");
104 | return kIOReturnInvalid;
105 | }
106 |
107 | // Guard: Start the transaction and set the access offset successfully
108 | IOReturn retVal = advSeekI2COverAUX(that, framebuffer, displayPath, address, offset, flags);
109 | if (retVal != kIOReturnSuccess) {
110 | SYSLOG("igfx", "I2C: AdvReadI2COverAUX() Error: Failed to set the data offset.");
111 | return retVal;
112 | }
113 |
114 | // Process the read request
115 | // ReadI2COverAUX() can only process up to 16 bytes in one AUX transaction
116 | // because the burst data size is 20 bytes, in which the first 4 bytes are used for the AUX message header
117 | while (length != 0) {
118 | // Calculate the new length for this I2C-over-AUX transaction
119 | uint16_t newLength = length >= 16 ? 16 : length;
120 |
121 | // This is an intermediate transaction
122 | retVal = wrapReadI2COverAUX(that, framebuffer, displayPath, address, newLength, buffer, true, flags);
123 |
124 | // Guard: The intermediate transaction succeeded
125 | if (retVal != kIOReturnSuccess) {
126 | // Terminate the transaction
127 | wrapReadI2COverAUX(that, framebuffer, displayPath, address, 0, nullptr, false, flags);
128 | return retVal;
129 | }
130 |
131 | // Update the buffer position and length
132 | length -= newLength;
133 | buffer += newLength;
134 | }
135 |
136 | // All intermediate transactions succeeded
137 | // Terminate the transaction
138 | return wrapReadI2COverAUX(that, framebuffer, displayPath, address, 0, nullptr, false, flags);
139 | }
140 |
141 | IOReturn IGFX::AdvancedI2COverAUXSupport::advWriteI2COverAUX(void *that, IORegistryEntry *framebuffer, void *displayPath, uint32_t address, uint32_t offset, uint16_t length, uint8_t *buffer, uint8_t flags) {
142 | // Guard: Check the buffer length
143 | if (length == 0) {
144 | SYSLOG("igfx", "I2C: AdvWriteI2COverAUX() Error: Buffer length must be non-zero.");
145 | return kIOReturnInvalid;
146 | }
147 |
148 | // Guard: Check the buffer
149 | if (buffer == nullptr) {
150 | SYSLOG("igfx", "I2C: AdvWriteI2COverAUX() Error: Buffer cannot be NULL.");
151 | return kIOReturnInvalid;
152 | }
153 |
154 | // Guard: Start the transaction and set the access offset successfully
155 | IOReturn retVal = advSeekI2COverAUX(that, framebuffer, displayPath, address, offset, flags);
156 | if (retVal != kIOReturnSuccess) {
157 | SYSLOG("igfx", "I2C: AdvWriteI2COverAUX() Error: Failed to set the data offset.");
158 | return retVal;
159 | }
160 |
161 | // Process the write request
162 | // WriteI2COverAUX() can only process up to 16 bytes in one AUX transaction
163 | // because the burst data size is 20 bytes, in which the first 4 bytes are used for the AUX message header
164 | while (length != 0) {
165 | // Calculate the new length for this I2C-over-AUX transaction
166 | uint16_t newLength = length >= 16 ? 16 : length;
167 |
168 | // This is an intermediate transaction
169 | retVal = wrapWriteI2COverAUX(that, framebuffer, displayPath, address, newLength, buffer, true);
170 |
171 | // Guard: The intermediate transaction succeeded
172 | if (retVal != kIOReturnSuccess) {
173 | // Terminate the transaction
174 | wrapWriteI2COverAUX(that, framebuffer, displayPath, address, 0, nullptr, false);
175 | return retVal;
176 | }
177 |
178 | // Update the buffer position and length
179 | length -= newLength;
180 | buffer += newLength;
181 | }
182 |
183 | // All intermediate transactions succeeded
184 | // Terminate the transaction
185 | return wrapWriteI2COverAUX(that, framebuffer, displayPath, address, 0, nullptr, false);
186 | }
187 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_igfx_kexts.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_igfx_kexts.cpp
3 | // WhateverGreen
4 | //
5 | // Created by FireWolf on 8/6/21.
6 | // Copyright © 2021 vit9696. All rights reserved.
7 | //
8 |
9 | #include "kern_igfx_kexts.hpp"
10 |
11 | static const char *pathIntelHD[] { "/System/Library/Extensions/AppleIntelHDGraphics.kext/Contents/MacOS/AppleIntelHDGraphics" };
12 | static const char *pathIntelHDFb[] { "/System/Library/Extensions/AppleIntelHDGraphicsFB.kext/Contents/MacOS/AppleIntelHDGraphicsFB" };
13 | static const char *pathIntelHD3000[] { "/System/Library/Extensions/AppleIntelHD3000Graphics.kext/Contents/MacOS/AppleIntelHD3000Graphics" };
14 | static const char *pathIntelSNBFb[] { "/System/Library/Extensions/AppleIntelSNBGraphicsFB.kext/Contents/MacOS/AppleIntelSNBGraphicsFB" };
15 | static const char *pathIntelHD4000[] { "/System/Library/Extensions/AppleIntelHD4000Graphics.kext/Contents/MacOS/AppleIntelHD4000Graphics" };
16 | static const char *pathIntelCapriFb[] { "/System/Library/Extensions/AppleIntelFramebufferCapri.kext/Contents/MacOS/AppleIntelFramebufferCapri" };
17 | static const char *pathIntelHD5000[] { "/System/Library/Extensions/AppleIntelHD5000Graphics.kext/Contents/MacOS/AppleIntelHD5000Graphics" };
18 | static const char *pathIntelAzulFb[] { "/System/Library/Extensions/AppleIntelFramebufferAzul.kext/Contents/MacOS/AppleIntelFramebufferAzul" };
19 | static const char *pathIntelBDW[] { "/System/Library/Extensions/AppleIntelBDWGraphics.kext/Contents/MacOS/AppleIntelBDWGraphics" };
20 | static const char *pathIntelBDWFb[] { "/System/Library/Extensions/AppleIntelBDWGraphicsFramebuffer.kext/Contents/MacOS/AppleIntelBDWGraphicsFramebuffer" };
21 | static const char *pathIntelSKL[] { "/System/Library/Extensions/AppleIntelSKLGraphics.kext/Contents/MacOS/AppleIntelSKLGraphics" };
22 | static const char *pathIntelSKLFb[] { "/System/Library/Extensions/AppleIntelSKLGraphicsFramebuffer.kext/Contents/MacOS/AppleIntelSKLGraphicsFramebuffer" };
23 | static const char *pathIntelKBL[] { "/System/Library/Extensions/AppleIntelKBLGraphics.kext/Contents/MacOS/AppleIntelKBLGraphics" };
24 | static const char *pathIntelKBLFb[] { "/System/Library/Extensions/AppleIntelKBLGraphicsFramebuffer.kext/Contents/MacOS/AppleIntelKBLGraphicsFramebuffer" };
25 | static const char *pathIntelCFLFb[] { "/System/Library/Extensions/AppleIntelCFLGraphicsFramebuffer.kext/Contents/MacOS/AppleIntelCFLGraphicsFramebuffer" };
26 | static const char *pathIntelCNL[] { "/System/Library/Extensions/AppleIntelCNLGraphics.kext/Contents/MacOS/AppleIntelCNLGraphics" };
27 | static const char *pathIntelCNLFb[] { "/System/Library/Extensions/AppleIntelCNLGraphicsFramebuffer.kext/Contents/MacOS/AppleIntelCNLGraphicsFramebuffer" };
28 | static const char *pathIntelICL[] { "/System/Library/Extensions/AppleIntelICLGraphics.kext/Contents/MacOS/AppleIntelICLGraphics" };
29 | static const char *pathIntelICLLPFb[] { "/System/Library/Extensions/AppleIntelICLLPGraphicsFramebuffer.kext/Contents/MacOS/AppleIntelICLLPGraphicsFramebuffer" };
30 | static const char *pathIntelICLHPFb[] { "/System/Library/Extensions/AppleIntelICLHPGraphicsFramebuffer.kext/Contents/MacOS/AppleIntelICLHPGraphicsFramebuffer" };
31 |
32 | KernelPatcher::KextInfo kextIntelHD { "com.apple.driver.AppleIntelHDGraphics", pathIntelHD, arrsize(pathIntelHD), {}, {}, KernelPatcher::KextInfo::Unloaded };
33 | KernelPatcher::KextInfo kextIntelHDFb { "com.apple.driver.AppleIntelHDGraphicsFB", pathIntelHDFb, arrsize(pathIntelHDFb), {}, {}, KernelPatcher::KextInfo::Unloaded };
34 | KernelPatcher::KextInfo kextIntelHD3000 { "com.apple.driver.AppleIntelHD3000Graphics", pathIntelHD3000, arrsize(pathIntelHD3000), {}, {}, KernelPatcher::KextInfo::Unloaded };
35 | KernelPatcher::KextInfo kextIntelSNBFb { "com.apple.driver.AppleIntelSNBGraphicsFB", pathIntelSNBFb, arrsize(pathIntelSNBFb), {}, {}, KernelPatcher::KextInfo::Unloaded };
36 | KernelPatcher::KextInfo kextIntelHD4000 { "com.apple.driver.AppleIntelHD4000Graphics", pathIntelHD4000, arrsize(pathIntelHD4000), {}, {}, KernelPatcher::KextInfo::Unloaded };
37 | KernelPatcher::KextInfo kextIntelCapriFb { "com.apple.driver.AppleIntelFramebufferCapri", pathIntelCapriFb, arrsize(pathIntelCapriFb), {}, {}, KernelPatcher::KextInfo::Unloaded };
38 | KernelPatcher::KextInfo kextIntelHD5000 { "com.apple.driver.AppleIntelHD5000Graphics", pathIntelHD5000, arrsize(pathIntelHD5000), {}, {}, KernelPatcher::KextInfo::Unloaded };
39 | KernelPatcher::KextInfo kextIntelAzulFb { "com.apple.driver.AppleIntelFramebufferAzul", pathIntelAzulFb, arrsize(pathIntelAzulFb), {}, {}, KernelPatcher::KextInfo::Unloaded };
40 | KernelPatcher::KextInfo kextIntelBDW { "com.apple.driver.AppleIntelBDWGraphics", pathIntelBDW, arrsize(pathIntelBDW), {}, {}, KernelPatcher::KextInfo::Unloaded };
41 | KernelPatcher::KextInfo kextIntelBDWFb { "com.apple.driver.AppleIntelBDWGraphicsFramebuffer", pathIntelBDWFb, arrsize(pathIntelBDWFb), {}, {}, KernelPatcher::KextInfo::Unloaded };
42 | KernelPatcher::KextInfo kextIntelSKL { "com.apple.driver.AppleIntelSKLGraphics", pathIntelSKL, arrsize(pathIntelSKL), {}, {}, KernelPatcher::KextInfo::Unloaded };
43 | KernelPatcher::KextInfo kextIntelSKLFb { "com.apple.driver.AppleIntelSKLGraphicsFramebuffer", pathIntelSKLFb, arrsize(pathIntelSKLFb), {}, {}, KernelPatcher::KextInfo::Unloaded };
44 | KernelPatcher::KextInfo kextIntelKBL { "com.apple.driver.AppleIntelKBLGraphics", pathIntelKBL, arrsize(pathIntelKBL), {}, {}, KernelPatcher::KextInfo::Unloaded };
45 | KernelPatcher::KextInfo kextIntelKBLFb { "com.apple.driver.AppleIntelKBLGraphicsFramebuffer", pathIntelKBLFb, arrsize(pathIntelKBLFb), {}, {}, KernelPatcher::KextInfo::Unloaded };
46 | KernelPatcher::KextInfo kextIntelCFLFb { "com.apple.driver.AppleIntelCFLGraphicsFramebuffer", pathIntelCFLFb, arrsize(pathIntelCFLFb), {}, {}, KernelPatcher::KextInfo::Unloaded };
47 | KernelPatcher::KextInfo kextIntelCNL { "com.apple.driver.AppleIntelCNLGraphics", pathIntelCNL, arrsize(pathIntelCNL), {}, {}, KernelPatcher::KextInfo::Unloaded };
48 | KernelPatcher::KextInfo kextIntelCNLFb { "com.apple.driver.AppleIntelCNLGraphicsFramebuffer", pathIntelCNLFb, arrsize(pathIntelCNLFb), {}, {}, KernelPatcher::KextInfo::Unloaded };
49 | KernelPatcher::KextInfo kextIntelICL { "com.apple.driver.AppleIntelICLGraphics", pathIntelICL, arrsize(pathIntelICL), {}, {}, KernelPatcher::KextInfo::Unloaded };
50 | KernelPatcher::KextInfo kextIntelICLLPFb { "com.apple.driver.AppleIntelICLLPGraphicsFramebuffer", pathIntelICLLPFb, arrsize(pathIntelICLLPFb), {}, {}, KernelPatcher::KextInfo::Unloaded };
51 | KernelPatcher::KextInfo kextIntelICLHPFb { "com.apple.driver.AppleIntelICLHPGraphicsFramebuffer", pathIntelICLHPFb, arrsize(pathIntelICLHPFb), {}, {}, KernelPatcher::KextInfo::Unloaded };
52 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_igfx_kexts.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_igfx_kexts.hpp
3 | // WhateverGreen
4 | //
5 | // Created by FireWolf on 8/6/21.
6 | // Copyright © 2021 vit9696. All rights reserved.
7 | //
8 |
9 | #ifndef kern_igfx_kexts_hpp
10 | #define kern_igfx_kexts_hpp
11 |
12 | #include
13 |
14 | extern KernelPatcher::KextInfo kextIntelHD;
15 | extern KernelPatcher::KextInfo kextIntelHDFb;
16 | extern KernelPatcher::KextInfo kextIntelHD3000;
17 | extern KernelPatcher::KextInfo kextIntelSNBFb;
18 | extern KernelPatcher::KextInfo kextIntelHD4000;
19 | extern KernelPatcher::KextInfo kextIntelCapriFb;
20 | extern KernelPatcher::KextInfo kextIntelHD5000;
21 | extern KernelPatcher::KextInfo kextIntelAzulFb;
22 | extern KernelPatcher::KextInfo kextIntelBDW;
23 | extern KernelPatcher::KextInfo kextIntelBDWFb;
24 | extern KernelPatcher::KextInfo kextIntelSKL;
25 | extern KernelPatcher::KextInfo kextIntelSKLFb;
26 | extern KernelPatcher::KextInfo kextIntelKBL;
27 | extern KernelPatcher::KextInfo kextIntelKBLFb;
28 | extern KernelPatcher::KextInfo kextIntelCFLFb;
29 | extern KernelPatcher::KextInfo kextIntelCNL;
30 | extern KernelPatcher::KextInfo kextIntelCNLFb;
31 | extern KernelPatcher::KextInfo kextIntelICL;
32 | extern KernelPatcher::KextInfo kextIntelICLLPFb;
33 | extern KernelPatcher::KextInfo kextIntelICLHPFb;
34 |
35 | #endif /* kern_igfx_kexts_hpp */
36 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_igfx_pm.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_igfx_pm.cpp
3 | // WhateverGreen
4 | //
5 | // Created by Pb on 22/06/2020.
6 | // Copyright © 2020 vit9696. All rights reserved.
7 | //
8 |
9 | /*
10 | * Portions Copyright © 2013 Intel Corporation
11 | *
12 | * Permission is hereby granted, free of charge, to any person obtaining a
13 | * copy of this software and associated documentation files (the "Software"),
14 | * to deal in the Software without restriction, including without limitation
15 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 | * and/or sell copies of the Software, and to permit persons to whom the
17 | * Software is furnished to do so, subject to the following conditions:
18 | *
19 | * The above copyright notice and this permission notice (including the next
20 | * paragraph) shall be included in all copies or substantial portions of the
21 | * Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29 | * IN THE SOFTWARE.
30 | */
31 |
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 |
41 | #include "kern_igfx.hpp"
42 |
43 | namespace {
44 | constexpr const char* log = "igfx_pm";
45 |
46 | // For debugging
47 | struct [[gnu::packed]] IGHwCsDesc {
48 | char type;
49 | char gap[4];
50 | char *title;
51 | char unk0[48];
52 | char unk1[12];
53 | };
54 |
55 | constexpr uint32_t MCHBAR_MIRROR_BASE_SNB = 0x140000;
56 | constexpr uint32_t GEN6_RP_STATE_CAP = MCHBAR_MIRROR_BASE_SNB + 0x5998;
57 |
58 | constexpr uint32_t GEN9_FREQUENCY_SHIFT = 23;
59 | constexpr uint32_t GEN9_FREQ_SCALER = 3;
60 |
61 | constexpr uint32_t FORCEWAKE_KERNEL_FALLBACK = 1 << 15;
62 |
63 | constexpr uint32_t FORCEWAKE_ACK_TIMEOUT_MS = 50;
64 |
65 | constexpr uint32_t FORCEWAKE_MEDIA_GEN9 = 0xa270;
66 | constexpr uint32_t FORCEWAKE_RENDER_GEN9 = 0xa278;
67 | constexpr uint32_t FORCEWAKE_BLITTER_GEN9 = 0xa188;
68 |
69 | constexpr uint32_t FORCEWAKE_ACK_MEDIA_GEN9 = 0x0D88;
70 | constexpr uint32_t FORCEWAKE_ACK_RENDER_GEN9 = 0x0D84;
71 | constexpr uint32_t FORCEWAKE_ACK_BLITTER_GEN9 = 0x130044;
72 |
73 | enum FORCEWAKE_DOM_BITS : unsigned {
74 | DOM_RENDER = 0b001,
75 | DOM_MEDIA = 0b010,
76 | DOM_BLITTER = 0b100,
77 | DOM_LAST = DOM_BLITTER,
78 | DOM_FIRST = DOM_RENDER
79 | };
80 |
81 | constexpr uint32_t regForDom(unsigned d) {
82 | if (d == DOM_RENDER)
83 | return FORCEWAKE_RENDER_GEN9;
84 | if (d == DOM_MEDIA)
85 | return FORCEWAKE_MEDIA_GEN9;
86 | if (d == DOM_BLITTER)
87 | return FORCEWAKE_BLITTER_GEN9;
88 | assertf(false, "Unknown force wake domain %d", d);
89 | return 0;
90 | }
91 |
92 | constexpr uint32_t ackForDom(unsigned d) {
93 | if (d == DOM_RENDER)
94 | return FORCEWAKE_ACK_RENDER_GEN9;
95 | if (d == DOM_MEDIA)
96 | return FORCEWAKE_ACK_MEDIA_GEN9;
97 | if (d == DOM_BLITTER)
98 | return FORCEWAKE_ACK_BLITTER_GEN9;
99 | assertf(false, "Unknown force wake domain %d", d);
100 | return 0;
101 | }
102 |
103 | constexpr const char* const strForDom(unsigned d) {
104 | if (d == DOM_RENDER)
105 | return "Render";
106 | if (d == DOM_MEDIA)
107 | return "Media";
108 | if (d == DOM_BLITTER)
109 | return "Blitter";
110 | return "(unk)";
111 | }
112 |
113 | constexpr uint32_t masked_field(uint32_t mask, uint32_t value) {
114 | return (mask << 16) | value;
115 | }
116 |
117 | constexpr uint32_t fw_set(uint32_t v) {
118 | return masked_field(v, v);
119 | }
120 |
121 | constexpr uint32_t fw_clear(uint32_t v) {
122 | return masked_field(v, 0);
123 | }
124 | }
125 |
126 | // MARK: - RPS Control Patch
127 |
128 | void IGFX::RPSControlPatch::init() {
129 | // We need to patch both drivers
130 | requiresPatchingGraphics = true;
131 | requiresPatchingFramebuffer = true;
132 |
133 | // Requires access to global framebuffer controllers
134 | requiresGlobalFramebufferControllersAccess = true;
135 |
136 | // Requires read access to MMIO registers
137 | requiresMMIORegistersReadAccess = true;
138 | }
139 |
140 | void IGFX::RPSControlPatch::processKernel(KernelPatcher &patcher, DeviceInfo *info) {
141 | uint32_t rpsc = 0;
142 | if (PE_parse_boot_argn("igfxrpsc", &rpsc, sizeof(rpsc)) ||
143 | WIOKit::getOSDataValue(info->videoBuiltin, "rps-control", rpsc)) {
144 | enabled = rpsc > 0 && available;
145 | DBGLOG("weg", "RPS control patch overriden (%u) availabile %d", rpsc, available);
146 | }
147 | }
148 |
149 | void IGFX::RPSControlPatch::processFramebufferKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
150 | KernelPatcher::RouteRequest routeRequest = {
151 | "__ZL15pmNotifyWrapperjjPyPj",
152 | wrapPmNotifyWrapper,
153 | orgPmNotifyWrapper
154 | };
155 |
156 | if (!patcher.routeMultiple(index, &routeRequest, 1, address, size))
157 | SYSLOG(log, "Failed to route pmNotifyWrapper.");
158 | }
159 |
160 | void IGFX::RPSControlPatch::processGraphicsKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
161 | // Address of `IGHardwareCommandStreamer2::submitExecList`
162 | mach_vm_address_t orgSubmitExecList;
163 |
164 | KernelPatcher::SolveRequest request = {
165 | getKernelVersion() >= KernelVersion::Catalina ? "__ZN26IGHardwareCommandStreamer514submitExecListEj" : "__ZN26IGHardwareCommandStreamer214submitExecListEj",
166 | orgSubmitExecList
167 | };
168 |
169 | if (!patcher.solveMultiple(index, &request, 1, address, size)) {
170 | SYSLOG(log, "Failed to solve the symbol for submitExecList.");
171 | return;
172 | }
173 |
174 | // `submitExecList()` only controls RPS for RCS type streamers
175 | // Patch it to enable control for any kind of streamer
176 | if (!patchRCSCheck(orgSubmitExecList))
177 | SYSLOG(log, "Failed to patch RCS check.");
178 | }
179 |
180 | int IGFX::RPSControlPatch::wrapPmNotifyWrapper(unsigned int a0, unsigned int a1, unsigned long long *a2, unsigned int *freq) {
181 | // Request the maximum RPS at exec list submission
182 | // While this sounds dangerous, we are still getting proper power management due to force wake clears.
183 | uint32_t cfreq = 0;
184 | callbackIGFX->modRPSControlPatch.orgPmNotifyWrapper(a0, a1, a2, &cfreq);
185 |
186 | if (!callbackIGFX->modRPSControlPatch.freq_max) {
187 | callbackIGFX->modRPSControlPatch.freq_max = callbackIGFX->readRegister32(callbackIGFX->defaultController(), GEN6_RP_STATE_CAP) & 0xFF;
188 | DBGLOG("log", "Read RP0 %d", callbackIGFX->modRPSControlPatch.freq_max);
189 | }
190 |
191 | *freq = (GEN9_FREQ_SCALER << GEN9_FREQUENCY_SHIFT) * callbackIGFX->modRPSControlPatch.freq_max;
192 | return 0;
193 | }
194 |
195 | bool IGFX::RPSControlPatch::patchRCSCheck(mach_vm_address_t& start) {
196 | constexpr unsigned ninsts_max {256};
197 |
198 | hde64s dis;
199 |
200 | bool found_cmp = false;
201 | bool found_jmp = false;
202 |
203 | for (size_t i = 0; i < ninsts_max; i++) {
204 | auto sz = Disassembler::hdeDisasm(start, &dis);
205 |
206 | if (dis.flags & F_ERROR) {
207 | SYSLOG(log, "Error disassembling submitExecList");
208 | break;
209 | }
210 |
211 | /* cmp byte ptr [rcx], 0 */
212 | if (!found_cmp && dis.opcode == 0x80 && dis.modrm_reg == 7 && dis.modrm_rm == 1)
213 | found_cmp = true;
214 | /* jnz rel32 */
215 | if (found_cmp && dis.opcode == 0x0f && dis.opcode2 == 0x85) {
216 | found_jmp = true;
217 | break;
218 | }
219 |
220 | start += sz;
221 | }
222 |
223 | if (found_jmp) {
224 | auto status = MachInfo::setKernelWriting(true, KernelPatcher::kernelWriteLock);
225 | if (status == KERN_SUCCESS) {
226 | constexpr uint8_t nop6[] {0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
227 | lilu_os_memcpy(reinterpret_cast(start), nop6, arrsize(nop6));
228 | MachInfo::setKernelWriting(false, KernelPatcher::kernelWriteLock);
229 | DBGLOG(log, "Patched submitExecList");
230 | return true;
231 | } else {
232 | DBGLOG(log, "Failed to set kernel writing");
233 | return false;
234 | }
235 | } else {
236 | SYSLOG(log, "jnz in submitExecList not found");
237 | return false;
238 | }
239 | }
240 |
241 | // MARK: - Force Wake Workaround
242 |
243 | bool IGFX::ForceWakeWorkaround::pollRegister(uint32_t reg, uint32_t val, uint32_t mask, uint32_t timeout) {
244 | AbsoluteTime now, deadline;
245 |
246 | clock_interval_to_deadline(timeout, kMillisecondScale, &deadline);
247 |
248 | for (clock_get_uptime(&now); now < deadline; clock_get_uptime(&now)) {
249 | auto rd = callbackIGFX->readRegister32(callbackIGFX->defaultController(), reg);
250 |
251 | // DBGLOG(log, "Rd 0x%x = 0x%x, expected 0x%x", reg, rd, val);
252 |
253 | if ((rd & mask) == val)
254 | return true;
255 | }
256 |
257 | return false;
258 | }
259 |
260 | bool IGFX::ForceWakeWorkaround::forceWakeWaitAckFallback(uint32_t d, uint32_t val, uint32_t mask) {
261 | unsigned pass = 1;
262 | bool ack = false;
263 | auto controller = callbackIGFX->defaultController();
264 |
265 | do {
266 | pollRegister(ackForDom(d), 0, FORCEWAKE_KERNEL_FALLBACK, FORCEWAKE_ACK_TIMEOUT_MS);
267 | callbackIGFX->writeRegister32(controller, regForDom(d), fw_set(FORCEWAKE_KERNEL_FALLBACK));
268 |
269 | IODelay(10 * pass);
270 | pollRegister(ackForDom(d), FORCEWAKE_KERNEL_FALLBACK, FORCEWAKE_KERNEL_FALLBACK, FORCEWAKE_ACK_TIMEOUT_MS);
271 |
272 | ack = (callbackIGFX->readRegister32(controller, ackForDom(d)) & mask) == val;
273 |
274 | callbackIGFX->writeRegister32(controller, regForDom(d), fw_clear(FORCEWAKE_KERNEL_FALLBACK));
275 | } while (!ack && pass++ < 10);
276 |
277 | // DBGLOG(log, "Force wake fallback used to %s %s in %u passes", set ? "set" : "clear", strForDom(d), pass);
278 |
279 | return ack;
280 | }
281 |
282 | /**
283 | * Port of i915 force wake. The difference with Apple code is as follows:
284 | * 1. 50 ms ACK timeouts, see https://patchwork.kernel.org/patch/7057561/
285 | * Apple code uses 90 ms.
286 | * 2. Use reserve bit as a fallback at primary ACK timeout, see https://patchwork.kernel.org/patch/10029821/
287 | */
288 |
289 | // NOTE: We are either in IRQ context, or in a spinlock critical section
290 | void IGFX::ForceWakeWorkaround::forceWake(void*, uint8_t set, uint32_t dom, uint32_t ctx) {
291 | // ctx 2: IRQ, 1: normal
292 |
293 | uint32_t ack_exp = set << ctx;
294 | uint32_t mask = 1 << ctx;
295 | uint32_t wr = ack_exp | (1 << ctx << 16);
296 |
297 | for (unsigned d = DOM_FIRST; d <= DOM_LAST; d <<= 1)
298 | if (dom & d) {
299 | callbackIGFX->writeRegister32(callbackIGFX->defaultController(), regForDom(d), wr);
300 | IOPause(100);
301 | if (!pollRegister(ackForDom(d), ack_exp, mask, FORCEWAKE_ACK_TIMEOUT_MS) &&
302 | !forceWakeWaitAckFallback(d, ack_exp, mask) &&
303 | !pollRegister(ackForDom(d), ack_exp, mask, FORCEWAKE_ACK_TIMEOUT_MS))
304 | PANIC(log, "ForceWake timeout for domain %s, expected 0x%x", strForDom(dom), ack_exp);
305 | }
306 | }
307 |
308 | void IGFX::ForceWakeWorkaround::init() {
309 | // We only need to patch the acceleration driver
310 | requiresPatchingGraphics = true;
311 |
312 | // Requires access to global framebuffer controllers
313 | requiresGlobalFramebufferControllersAccess = true;
314 |
315 | // Requires read and write access to MMIO registers
316 | requiresMMIORegistersReadAccess = true;
317 | requiresMMIORegistersWriteAccess = true;
318 | }
319 |
320 | void IGFX::ForceWakeWorkaround::processGraphicsKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
321 | KernelPatcher::RouteRequest request = {
322 | "__ZN16IntelAccelerator26SafeForceWakeMultithreadedEbjj",
323 | forceWake
324 | };
325 |
326 | if (!patcher.routeMultiple(index, &request, 1, address, size))
327 | SYSLOG("igfx", "Failed to route SafeForceWake.");
328 | }
329 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_ngfx.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_ngfx.hpp
3 | // WhateverGreen
4 | //
5 | // Copyright © 2018 vit9696. All rights reserved.
6 | //
7 |
8 | #ifndef kern_ngfx_hpp
9 | #define kern_ngfx_hpp
10 |
11 | #include
12 |
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | // Assembly exports for restoreLegacyOptimisations
19 | extern "C" bool wrapVaddrPreSubmitTrampoline(void *that);
20 | extern "C" bool orgVaddrPresubmitTrampoline(void *that);
21 | extern "C" bool (*orgVaddrPreSubmit)(void *addr);
22 |
23 | class NGFX {
24 | public:
25 | void init();
26 | void deinit();
27 |
28 | /**
29 | * Property patching routine
30 | *
31 | * @param patcher KernelPatcher instance
32 | * @param info device info
33 | */
34 | void processKernel(KernelPatcher &patcher, DeviceInfo *info);
35 |
36 | /**
37 | * Patch kext if needed and prepare other patches
38 | *
39 | * @param patcher KernelPatcher instance
40 | * @param index kinfo handle
41 | * @param address kinfo load address
42 | * @param size kinfo memory size
43 | *
44 | * @return true if patched anything
45 | */
46 | bool processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size);
47 |
48 | private:
49 | /**
50 | * Private self instance for callbacks
51 | */
52 | static NGFX *callbackNGFX;
53 |
54 | /**
55 | * NVIDIA Apple Developer Team ID used for permission override
56 | */
57 | static constexpr const char *NvidiaTeamId { "6KR3T733EC" };
58 |
59 | /**
60 | * Force Web Driver compatibility, -1 lets us override via GPU property
61 | */
62 | int forceDriverCompatibility {-1};
63 |
64 | /**
65 | * Virtual address submission performance fix
66 | */
67 | int fifoSubmit {-1};
68 |
69 | /**
70 | * Enable debug logging in NVIDIA drivers
71 | */
72 | bool enableDebugLogging {false};
73 |
74 | /**
75 | * Disable team unrestriction patches fixing visual glitches on 10.12 with Web drivers
76 | */
77 | bool disableTeamUnrestrict {false};
78 |
79 | /**
80 | * nvGpFifoChannel::PreSubmit function type
81 | */
82 | using t_fifoPreSubmit = bool (*)(void *, uint32_t, void *, uint32_t, void *, uint32_t *, uint64_t, uint32_t);
83 |
84 | /**
85 | * Pointer to nvGpFifoChannel::Prepare function
86 | */
87 | bool (*orgFifoPrepare)(void *fifo) {nullptr};
88 |
89 | /**
90 | * Pointer to nvGpFifoChannel::Complete function
91 | */
92 | void (*orgFifoComplete)(void *fifo) {nullptr};
93 |
94 | /**
95 | * Pointer to csfg_get_teamid function
96 | */
97 | const char *(*orgCsfgGetTeamId)(void *fg) {nullptr};
98 |
99 | /**
100 | * Original csfg_get_platform_binary function
101 | */
102 | mach_vm_address_t orgCsfgGetPlatformBinary {};
103 |
104 | /**
105 | * Original SetAccelProperties functions for official and web drivers
106 | */
107 | mach_vm_address_t orgSetAccelProperties {};
108 | mach_vm_address_t orgSetAccelPropertiesWeb {};
109 |
110 | /**
111 | * Original NVDAStartupWeb::probe function
112 | */
113 | mach_vm_address_t orgStartupWebProbe {};
114 |
115 | /**
116 | * Original IONDRVFramebuffer::_doControl function
117 | */
118 | mach_vm_address_t orgNdrvDoControl {};
119 |
120 | /**
121 | * Restore legacy optimisations from 10.13.0, which fix lags for Kepler GPUs.
122 | * For Web drivers it is very experimental, since they have a lot of additional different (broken) code.
123 | *
124 | * @param patcher KernelPatcher instance
125 | * @param index kinfo handle
126 | * @param address kinfo load address
127 | * @param size kinfo memory size
128 | */
129 | void restoreLegacyOptimisations(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size);
130 |
131 | /**
132 | * Add IOVARenderer properties to fix hardware video decoding
133 | *
134 | * @param that accelerator instance
135 | */
136 | void applyAcceleratorProperties(IOService *that);
137 |
138 | /**
139 | * csfg_get_platform_binary wrapper used for fixing visual glitches with web drivers due to missing entitlements.
140 | *
141 | * @param fg codesign information
142 | *
143 | * @result 1 if the binary has platform access rights
144 | */
145 | static int wrapCsfgGetPlatformBinary(void *fg);
146 |
147 | /**
148 | * csfg_get_platform_binary wrapper used for fixing visual glitches with web drivers due to missing entitlements.
149 | *
150 | * @param fg codesign information
151 | *
152 | * @result 1 if the binary is platform
153 | */
154 | static bool wrapVaddrPreSubmit(void *that);
155 |
156 | /**
157 | * SetAccelProperties wrapper used to add IOVARenderer properties
158 | */
159 | static void wrapSetAccelProperties(IOService *that);
160 | static void wrapSetAccelPropertiesWeb(IOService *that);
161 |
162 | /**
163 | * NVDAStartup::probe wrapper used to force-enable web-drivers
164 | */
165 | static IOService *wrapStartupWebProbe(IOService *that, IOService *provider, SInt32 *score);
166 |
167 | /**
168 | * IONDRVFramebuffer::_doControl wrapper used to avoid debug spam
169 | */
170 | static IOReturn wrapNdrvDoControl(IONDRVFramebuffer *fb, UInt32 code, void *params);
171 |
172 | /**
173 | * nvErrorLog_va replacement with logging support
174 | */
175 | static void resmanErrorLogVA(void *context, uint32_t id, const char *format, ...);
176 | };
177 |
178 | #endif /* kern_ngfx_hpp */
179 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_ngfx_asm.S:
--------------------------------------------------------------------------------
1 | //
2 | // kern_ngfx_asm.S
3 | // WhateverGreen
4 | //
5 | // Copyright © 2018 vit9696. All rights reserved.
6 | //
7 |
8 | #define PRESUBMIT_FROM_REG(x, y) \
9 | push %rdi; \
10 | push %rsi; \
11 | push %rdx; \
12 | push %rcx; \
13 | push %r8; \
14 | push %r9; \
15 | push %r10; \
16 | push %r11; \
17 | mov x, %rdi; \
18 | call y; \
19 | pop %r11; \
20 | pop %r10; \
21 | pop %r9; \
22 | pop %r8; \
23 | pop %rcx; \
24 | pop %rdx; \
25 | pop %rsi; \
26 | pop %rdi; \
27 | ret;
28 |
29 | .text
30 | .globl _wrapVaddrPreSubmitTrampoline
31 | _wrapVaddrPreSubmitTrampoline:
32 | // Choose the routing
33 | test %al, %al
34 | // Standard routing (for normal calls)
35 | jz __ZN4NGFX18wrapVaddrPreSubmitEPv
36 | // Wrapped routing (for patched calls)
37 | cmp $1,%al
38 | jz handle_rbx_off
39 | cmp $2,%al
40 | jz handle_r13_off
41 | cmp $3,%al
42 | jz handle_r12_off
43 | // Do we need more registers?
44 | ud2
45 | handle_rbx_off:
46 | PRESUBMIT_FROM_REG(%rbx, __ZN4NGFX18wrapVaddrPreSubmitEPv)
47 | handle_r13_off:
48 | PRESUBMIT_FROM_REG(%r13, __ZN4NGFX18wrapVaddrPreSubmitEPv)
49 | handle_r12_off:
50 | PRESUBMIT_FROM_REG(%r12, __ZN4NGFX18wrapVaddrPreSubmitEPv)
51 |
52 | .globl _orgVaddrPresubmitTrampoline
53 | _orgVaddrPresubmitTrampoline:
54 | // This is the prologue we patched out
55 | push %rbp
56 | mov %rsp, %rbp
57 | // Jump to the original code
58 | mov _orgVaddrPreSubmit(%rip), %rax
59 | jmp *%rax
60 |
61 | .data
62 | .globl _orgVaddrPreSubmit
63 | _orgVaddrPreSubmit:
64 | .rept 8
65 | .byte 0
66 | .endr
67 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_nvhda.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_nvhda.cpp
3 | // WhateverGreen
4 | //
5 | // Copyright © 2018 vit9696. All rights reserved.
6 | //
7 |
8 | #include "kern_nvhda.hpp"
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | // Workaround for systems with BIOSes that default-disable the HD Audio function on their NVIDIA GPUs.
16 | // We match the device with a higher IOProbeScore than the NVIDIA drivers, use our probe routine to
17 | // enable the HD Audio function, trigger a PCI rescan, and then return a probe failure so that the
18 | // real driver can continue to load.
19 | //
20 | // References:
21 | // https://bugs.freedesktop.org/show_bug.cgi?id=75985
22 | // https://devtalk.nvidia.com/default/topic/1024022/linux/gtx-1060-no-audio-over-hdmi-only-hda-intel-detected-azalia/
23 | // https://github.com/acidanthera/bugtracker/issues/292
24 |
25 | OSDefineMetaClassAndStructors(NVHDAEnabler, IOService);
26 |
27 | IOService* NVHDAEnabler::probe(IOService *provider, SInt32 *score) {
28 | auto pciDevice = OSDynamicCast(IOPCIDevice, provider);
29 | if (!pciDevice) {
30 | SYSLOG("NVHDAEnabler", "probe: pciDevice is NULL");
31 | return nullptr;
32 | }
33 |
34 | uint32_t hdaEnableDword = pciDevice->configRead32(HDAEnableReg);
35 | if (hdaEnableDword & HDAEnableBit) {
36 | DBGLOG("NVHDAEnabler", "probe: HDA enable bit is already set, nothing to do");
37 | return nullptr;
38 | }
39 |
40 | DBGLOG("NVHDAEnabler", "probe: reg is 0x%x, setting HDA enable bit", hdaEnableDword);
41 | hdaEnableDword |= HDAEnableBit;
42 | pciDevice->configWrite32(HDAEnableReg, hdaEnableDword);
43 |
44 | // Verify with readback
45 | DBGLOG("NVHDAEnabler", "probe: readback: reg is 0x%x", pciDevice->configRead32(HDAEnableReg));
46 |
47 | // Find the parent IOPCIBridge
48 | auto parentBridge = OSDynamicCast(IOPCIDevice, pciDevice->getParentEntry(gIODTPlane));
49 | if (!parentBridge) {
50 | DBGLOG("NVHDAEnabler", "probe: Can't find the parent bridge's IOPCIDevice");
51 | return nullptr;
52 | }
53 |
54 | DBGLOG("NVHDAEnabler", "probe: Requesting parent bridge rescan");
55 |
56 | // Mark this device and the parent bridge as needing scanning, then trigger the rescan.
57 | pciDevice->kernelRequestProbe(kIOPCIProbeOptionNeedsScan);
58 | parentBridge->kernelRequestProbe(kIOPCIProbeOptionNeedsScan | kIOPCIProbeOptionDone);
59 |
60 | // This probe must always fail so that the real driver can get a chance to load afterwards.
61 | return nullptr;
62 | }
63 |
64 | bool NVHDAEnabler::start(IOService *provider) {
65 | SYSLOG("NVHDAEnabler", "start: shouldn't be called!");
66 | return false;
67 | }
68 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_nvhda.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_nvhda.hpp
3 | // WhateverGreen
4 | //
5 | // Copyright © 2018 vit9696. All rights reserved.
6 | //
7 |
8 | #ifndef kern_nvhda_hpp
9 | #define kern_nvhda_hpp
10 |
11 | #include
12 | #include
13 |
14 | class EXPORT NVHDAEnabler : public IOService {
15 | OSDeclareDefaultStructors(NVHDAEnabler);
16 | static constexpr uint32_t HDAEnableReg = 0x488;
17 | static constexpr uint32_t HDAEnableBit = 0x02000000;
18 | public:
19 | IOService* probe(IOService *provider, SInt32 *score) override;
20 | bool start(IOService *provider) override;
21 | };
22 |
23 | #endif /* kern_nvhda_hpp */
24 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_shiki.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_shiki.hpp
3 | // WhateverGreen
4 | //
5 | // Copyright © 2018 vit9696. All rights reserved.
6 | //
7 |
8 | #ifndef kern_shiki_hpp
9 | #define kern_shiki_hpp
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | class SHIKI {
17 | public:
18 | void init();
19 | void deinit();
20 |
21 | /**
22 | * Property patching routine
23 | *
24 | * @param patcher KernelPatcher instance
25 | * @param info device info
26 | */
27 | void processKernel(KernelPatcher &patcher, DeviceInfo *info);
28 |
29 | private:
30 | // Aside generic DRM unlock patches, Shiki also provides a set of patches
31 | // to workaround various issues with hardware video acceleration support.
32 | // These are set as a shikigva boot-arg bitmask.
33 | // For example, to enable ForceOnlineRenderer, ExecutableWhitelist, and ReplaceBoardID
34 | // you sum 1 + 8 + 32 = 41 -> and pass shikigva=41.
35 | enum ShikiGVAPatches {
36 | // Remove forceOfflineRenderer from AppleGVA Info.plist.
37 | // This is required to allow hardware acceleration on several mac models with discrete GPUs
38 | // when only IGPU is available.
39 | // See /System/Library/PrivateFrameworks/AppleGVA.framework/Resources/Info.plist for more details.
40 | ForceOnlineRenderer = 1,
41 | // Remove hweBGRA from AppleGVA Info.plist.
42 | // hweBGRA is not supported by NVIDIA GPUs, so the patch is sometimes required when using NVIDIA
43 | // in a mac model meant to be used with AMD or Intel.
44 | // See /System/Library/PrivateFrameworks/AppleGVA.framework/Resources/Info.plist for more details.
45 | AllowNonBGRA = 2,
46 | // Prior to 10.13.4 certain GPU+CPU combinations were not meant to provide hardware acceleration and had to be patched.
47 | // The overall problematic configuration list is: NVIDIA+BDW, NVIDIA+SKL, NVIDIA+KBL, AMD+IVB, NVIDIA+SNB.
48 | // Enabled automatically if shikigva is *NOT* passed on 10.13.3 and earlier. All are fixed in 10.13.4.
49 | ForceCompatibleRenderer = 4,
50 | // Unlike 10.12.6 without security updates and earlier, on 10.13 and latest 10.12.6 AppleGVA patches
51 | // do not apply to all processes, and each process needs to be patched explicitly. This is a bug
52 | // in Lilu, which needs to be explored and fixed. For now this bit ensures that the processes present
53 | // in WHITELIST section of Patches.plist will definitely get the fixes even on 10.13 and 10.12.6.
54 | // On 10.12.6 and 10.13 this must be used if any of the following bits are used:
55 | // - ForceOnlineRenderer
56 | // - AllowNonBGRA
57 | // - ForceCompatibleRenderer
58 | // - ReplaceBoardID
59 | // - FixSandyBridgeClassName
60 | // It is enabled automatically on 10.12 and 10.13 if shikigva is *NOT* passed and ForceCompatibleRenderer or
61 | // FixSandyBridgeClassName are automatically enabled.
62 | AddExecutableWhitelist = 8,
63 | // Use hardware DRM decoder (normally AMD) by pretending to be iMacPro in apps that require it.
64 | // For example, in Music.app or TV.app for TV+.
65 | UseHwDrmDecoder = 16,
66 | // Replace board-id used by AppleGVA and AppleVPA by a different board-id.
67 | // Sometimes it is feasible to use different GPU acceleration settings from the main mac model.
68 | // By default Mac-27ADBB7B4CEE8E61 (iMac14,2) will be used, but you can override this via shiki-id boot-arg.
69 | // See /System/Library/PrivateFrameworks/AppleGVA.framework/Resources/Info.plist for more details.
70 | ReplaceBoardID = 32,
71 | // Attempt to support fps.2_1 (FairPlay 2.x) in Safari with hardware decoder. Works on most modern AMD GPUs.
72 | // Note, AMD Polaris Ellesmere is broken in 10.15 (e.g. RX 590), whereas AMD Polaris Baffin (e.g. RX 460) is fine.
73 | // Easiest check is to run WebKitMediaKeys.isTypeSupported("com.apple.fps.2_1", "video/mp4") in Safari Web Console.
74 | // Broken GPU driver will just freeze the system with .gpuRestart crash.
75 | UseHwDrmStreaming = 64,
76 | // Disables software decoder unlock patches for FairPlay 1.0.
77 | // This will use AMD decoder if available, but currently requires IGPU to be either not present or disabled.
78 | UseLegacyHwDrmDecoder = 128,
79 | // Enables software decoder unlock patches for FairPlay 4.0.
80 | // This will use software decoder, but currently requires IGPU to be either not present or disabled.
81 | UseSwDrmDecoder = 256,
82 | };
83 |
84 | /**
85 | * Current process information
86 | */
87 | UserPatcher::ProcInfo *procInfo {nullptr};
88 |
89 | /**
90 | * Current process information array size
91 | */
92 | size_t procInfoSize {0};
93 |
94 | /**
95 | * Automatic GPU detection is required
96 | */
97 | bool autodetectGFX {false};
98 |
99 | /**
100 | * Disable Shiki, based on mode
101 | */
102 | bool disableShiki {false};
103 |
104 | /**
105 | * Custom board-id set to /shiki-id IOReg to be used by AppleGVA
106 | */
107 | char customBoardID[21] {};
108 |
109 | /**
110 | * iMacPro1,1 board-id used for find-replace (thus the size).
111 | */
112 | uint8_t iMacProBoardId[21] = {"Mac-7BA5B2D9E42DDD94"};
113 |
114 | /**
115 | * Self board-id used for find-replace (thus the size).
116 | */
117 | uint8_t selfBoardId[21] = {};
118 |
119 | /**
120 | * Self mac model for find-replace (thus the size).
121 | */
122 | uint8_t selfMacModel[20] {};
123 |
124 | /**
125 | * Remove requested patches
126 | *
127 | * @param section section to remove patches from
128 | */
129 | void disableSection(uint32_t section);
130 |
131 | /**
132 | * Force compatible renderer patch
133 | *
134 | * @return true on success
135 | */
136 | bool setCompatibleRendererPatch();
137 |
138 | /**
139 | * Get patch by section
140 | */
141 | UserPatcher::BinaryModPatch *getPatchSection(uint32_t section);
142 | };
143 |
144 | #endif /* kern_shiki_hpp */
145 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_start.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_start.cpp
3 | // WhateverGreen
4 | //
5 | // Copyright © 2017 vit9696. All rights reserved.
6 | //
7 |
8 | #include
9 | #include
10 |
11 | #include "kern_weg.hpp"
12 |
13 | static WEG weg;
14 |
15 | static const char *bootargOff[] {
16 | "-wegoff"
17 | };
18 |
19 | static const char *bootargDebug[] {
20 | "-wegdbg"
21 | };
22 |
23 | static const char *bootargBeta[] {
24 | "-wegbeta"
25 | };
26 |
27 | PluginConfiguration ADDPR(config) {
28 | xStringify(PRODUCT_NAME),
29 | parseModuleVersion(xStringify(MODULE_VERSION)),
30 | LiluAPI::AllowNormal | LiluAPI::AllowInstallerRecovery | LiluAPI::AllowSafeMode,
31 | bootargOff,
32 | arrsize(bootargOff),
33 | bootargDebug,
34 | arrsize(bootargDebug),
35 | bootargBeta,
36 | arrsize(bootargBeta),
37 | KernelVersion::SnowLeopard,
38 | KernelVersion::Sequoia,
39 | []() {
40 | weg.init();
41 | }
42 | };
43 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_unfair.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_unfair.cpp
3 | // WhateverGreen
4 | //
5 | // Copyright © 2021 vit9696. All rights reserved.
6 | //
7 |
8 | #include "kern_unfair.hpp"
9 | #include "kern_weg.hpp"
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | UNFAIR *UNFAIR::callbackUNFAIR;
22 |
23 | void UNFAIR::init() {
24 | callbackUNFAIR = this;
25 |
26 | disableUnfair = !(lilu.getRunMode() & LiluAPI::RunningNormal);
27 | disableUnfair |= checkKernelArgument("-unfairoff");
28 |
29 | if (disableUnfair)
30 | return;
31 | }
32 |
33 | void UNFAIR::deinit() {
34 |
35 | }
36 |
37 | void UNFAIR::csValidatePage(vnode *vp, memory_object_t pager, memory_object_offset_t page_offset, const void *data, int *validated_p, int *tainted_p, int *nx_p) {
38 | FunctionCast(csValidatePage, callbackUNFAIR->orgCsValidatePage)(vp, pager, page_offset, data, validated_p, tainted_p, nx_p);
39 |
40 | char path[PATH_MAX];
41 | int pathlen = PATH_MAX;
42 | if (vn_getpath(vp, path, &pathlen) == 0) {
43 | //DBGLOG("unfair", "csValidatePage %s", path);
44 |
45 | if ((callbackUNFAIR->unfairGva & UnfairDyldSharedCache) != 0 && UserPatcher::matchSharedCachePath(path)) {
46 | if ((callbackUNFAIR->unfairGva & UnfairRelaxHdcpRequirements) != 0) {
47 | static const uint8_t find[29] = {
48 | 0x4D, 0x61, 0x63, 0x50, 0x72, 0x6F, 0x35, 0x2C, 0x31, 0x00, 0x4D, 0x61, 0x63, 0x50, 0x72, 0x6F,
49 | 0x36, 0x2C, 0x31, 0x00, 0x49, 0x4F, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65
50 | };
51 | if (UNLIKELY(KernelPatcher::findAndReplace(const_cast(data), PAGE_SIZE, find, sizeof(find), BaseDeviceInfo::get().modelIdentifier, 20)))
52 | DBGLOG("unfair", "patched relaxed drm model");
53 | }
54 |
55 | if ((callbackUNFAIR->unfairGva & UnfairCustomAppleGvaBoardId) != 0) {
56 | static const uint8_t find[18] = {
57 | 0x62, 0x6F, 0x61, 0x72, 0x64, 0x2D, 0x69, 0x64, 0x00, 0x68, 0x77, 0x2E, 0x6D, 0x6F, 0x64, 0x65,
58 | 0x6C
59 | };
60 | static const uint8_t repl[5] = {
61 | 0x68, 0x77, 0x67, 0x76, 0x61
62 | };
63 | if (UNLIKELY(KernelPatcher::findAndReplace(const_cast(data), PAGE_SIZE, find, sizeof(find), repl, sizeof(repl))))
64 | DBGLOG("unfair", "patched board-id -> hwgva-id");
65 | }
66 |
67 | } else if ((callbackUNFAIR->unfairGva & UnfairAllowHardwareDrmStreamDecoderOnOldCpuid) != 0 &&
68 | (UNLIKELY(strcmp(path, "/System/Library/PrivateFrameworks/CoreLSKDMSE.framework/Versions/A/CoreLSKDMSE") == 0) ||
69 | UNLIKELY(strcmp(path, "/System/Library/PrivateFrameworks/CoreLSKD.framework/Versions/A/CoreLSKD") == 0))) {
70 | static const uint8_t find[] = {0xC7, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x0F, 0xA2};
71 | static const uint8_t repl[] = {0xC7, 0xC0, 0xC3, 0x06, 0x03, 0x00, 0x90, 0x90};
72 | if (UNLIKELY(KernelPatcher::findAndReplace(const_cast(data), PAGE_SIZE, find, sizeof(find), repl, sizeof(repl))))
73 | DBGLOG("unfair", "patched streaming cpuid to haswell");
74 | }
75 | }
76 | }
77 |
78 | void UNFAIR::processKernel(KernelPatcher &patcher, DeviceInfo *info) {
79 | if (disableUnfair)
80 | return;
81 |
82 | WEG::getVideoArgument(info, "unfairgva", &unfairGva, sizeof(unfairGva));
83 | if (unfairGva == 0) {
84 | DBGLOG("unfair", "disabling unfair gva due to missing boot argument");
85 | disableUnfair = true;
86 | return;
87 | }
88 |
89 | DBGLOG("unfair", "activating with %d bitmask", unfairGva);
90 |
91 | if ((unfairGva & UnfairCustomAppleGvaBoardId) != 0) {
92 | auto entry = IORegistryEntry::fromPath("/", gIODTPlane);
93 | if (entry) {
94 | DBGLOG("unfair", "setting hwgva-id to iMacPro1,1");
95 | entry->setProperty("hwgva-id", const_cast("Mac-7BA5B2D9E42DDD94"), static_cast(sizeof("Mac-7BA5B2D9E42DDD94")));
96 | entry->release();
97 | } else {
98 | SYSLOG("shiki", "failed to obtain iodt tree");
99 | unfairGva &= ~UnfairCustomAppleGvaBoardId;
100 | }
101 | }
102 |
103 | KernelPatcher::RouteRequest csRoute("_cs_validate_page", csValidatePage, orgCsValidatePage);
104 | if (!patcher.routeMultipleLong(KernelPatcher::KernelID, &csRoute, 1)) {
105 | SYSLOG("unfair", "failed to route cs validation pages");
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_unfair.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_unfair.hpp
3 | // WhateverGreen
4 | //
5 | // Copyright © 2021 vit9696. All rights reserved.
6 | //
7 |
8 | #ifndef kern_unfair_hpp
9 | #define kern_unfair_hpp
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | class UNFAIR {
17 | public:
18 | void init();
19 | void deinit();
20 |
21 | /**
22 | * Property patching routine
23 | *
24 | * @param patcher KernelPatcher instance
25 | * @param info device info
26 | */
27 | void processKernel(KernelPatcher &patcher, DeviceInfo *info);
28 |
29 | private:
30 | /**
31 | * Private self instance for callbacks
32 | */
33 | static UNFAIR *callbackUNFAIR;
34 |
35 | /**
36 | * Disable unfair, based on mode
37 | */
38 | bool disableUnfair {false};
39 |
40 | /**
41 | * GVA bitmask as specified in unfairgva boot argument / property.
42 | */
43 | enum : uint32_t {
44 | UnfairAllowHardwareDrmStreamDecoderOnOldCpuid = 1,
45 | UnfairRelaxHdcpRequirements = 2,
46 | UnfairCustomAppleGvaBoardId = 4,
47 | UnfairDyldSharedCache = UnfairRelaxHdcpRequirements | UnfairCustomAppleGvaBoardId,
48 | };
49 |
50 | /**
51 | * Patch rule bitmask (0 means none).
52 | */
53 | uint32_t unfairGva {0};
54 |
55 | /**
56 | * Codesign page validation wrapper used for userspace patching
57 | */
58 | static void csValidatePage(vnode *vp, memory_object_t pager, memory_object_offset_t page_offset, const void *data, int *validated_p, int *tainted_p, int *nx_p);
59 |
60 | /**
61 | * Original codesign page validation pointer.
62 | */
63 | mach_vm_address_t orgCsValidatePage {0};
64 | };
65 |
66 | #endif /* kern_unfair_hpp */
67 |
--------------------------------------------------------------------------------
/WhateverGreen/kern_weg.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // kern_weg.hpp
3 | // WhateverGreen
4 | //
5 | // Copyright © 2018 vit9696. All rights reserved.
6 | //
7 |
8 | #ifndef kern_weg_hpp
9 | #define kern_weg_hpp
10 |
11 | #include
12 | #include
13 |
14 | #include "kern_cdf.hpp"
15 | #include "kern_igfx.hpp"
16 | #include "kern_ngfx.hpp"
17 | #include "kern_rad.hpp"
18 | #include "kern_shiki.hpp"
19 | #include "kern_unfair.hpp"
20 |
21 | class IOFramebuffer;
22 | class IODisplay;
23 |
24 | class WEG {
25 | public:
26 | void init();
27 | void deinit();
28 |
29 | /**
30 | * Get overridable boot argument from kernel args (priority) and GPU properties
31 | */
32 | static bool getVideoArgument(DeviceInfo *info, const char *name, void *bootarg, int size);
33 |
34 | private:
35 | /**
36 | * Private self instance for callbacks
37 | */
38 | static WEG *callbackWEG;
39 |
40 | /**
41 | * High resolution unlocker instances
42 | */
43 | CDF cdf;
44 |
45 | /**
46 | * Intel GPU fixes instances
47 | */
48 | IGFX igfx;
49 |
50 | /**
51 | * NVIDIA GPU fixes instance
52 | */
53 | NGFX ngfx;
54 |
55 | /**
56 | * Radeon GPU fixes instance
57 | */
58 | RAD rad;
59 |
60 | /**
61 | * Hardware acceleration and FairPlay fixes instance
62 | */
63 | SHIKI shiki;
64 |
65 | /**
66 | * FairPlay fixes for modern operating systems
67 | */
68 | UNFAIR unfair;
69 |
70 | /**
71 | * FB_DETECT autodetects based on the installed GPU.
72 | * FB_RESET enforces -v like usual patch.
73 | * FB_COPY enforces screen copy (default on IGPU).
74 | * FB_ZEROFILL erases screen content (default on AMD).
75 | * FB_NONE does nothing.
76 | */
77 | enum FramebufferFixMode {
78 | FB_DETECT = 0,
79 | FB_RESET = 1,
80 | FB_COPY = 2,
81 | FB_ZEROFILL = 3,
82 | FB_NONE = 4,
83 | FB_TOTAL = 5
84 | };
85 |
86 | /**
87 | * Framebuffer distortion fix mode
88 | */
89 | uint32_t resetFramebuffer {FB_DETECT};
90 |
91 | /**
92 | * APPLBKL_OFF disables AppleBacklight patches.
93 | * APPLBKL_ON enforces AppleBacklight patches.
94 | * APPLBKL_DETECT enables AppleBacklight patches for IGPU-only non-Apple setups.
95 | * APPLBKL_NAVI10 enables AppleBacklight patches for AMD Navi10 PWM backlight control.
96 | */
97 | enum BacklightPatchMode {
98 | APPLBKL_OFF = 0,
99 | APPLBKL_ON = 1,
100 | APPLBKL_DETECT = 2,
101 | APPLBKL_NAVI10 = 3
102 | };
103 |
104 | /**
105 | * applbkl boot-arg controlled AppleBacklight kext patch
106 | */
107 | uint32_t appleBacklightPatch {APPLBKL_DETECT};
108 |
109 | /**
110 | * applbkl custom device name if any
111 | */
112 | OSData *appleBacklightCustomName {nullptr};
113 |
114 | /**
115 | * applbkl custom device data if any
116 | */
117 | OSData *appleBacklightCustomData {nullptr};
118 |
119 | /**
120 | * Backlight panel data format
121 | */
122 | struct ApplePanelData {
123 | const char *deviceName;
124 | uint8_t deviceData[36];
125 | };
126 |
127 | /**
128 | * Backlight panel data
129 | */
130 | static ApplePanelData appleBacklightData[];
131 |
132 | /**
133 | * Console info structure, taken from osfmk/console/video_console.h
134 | * Last updated from XNU 4570.1.46.
135 | */
136 | struct vc_info {
137 | unsigned int v_height; /* pixels */
138 | unsigned int v_width; /* pixels */
139 | unsigned int v_depth;
140 | unsigned int v_rowbytes;
141 | unsigned long v_baseaddr;
142 | unsigned int v_type;
143 | char v_name[32];
144 | uint64_t v_physaddr;
145 | unsigned int v_rows; /* characters */
146 | unsigned int v_columns; /* characters */
147 | unsigned int v_rowscanbytes; /* Actualy number of bytes used for display per row*/
148 | unsigned int v_scale;
149 | unsigned int v_rotate;
150 | unsigned int v_reserved[3];
151 | };
152 |
153 | /**
154 | * Loaded vinfo
155 | */
156 | vc_info consoleVinfo {};
157 |
158 | /**
159 | * Console buffer backcopy
160 | */
161 | uint8_t *consoleBuffer {nullptr};
162 |
163 | /**
164 | * Original IOGraphics framebuffer init handler
165 | */
166 | mach_vm_address_t orgFramebufferInit {};
167 |
168 | /**
169 | * Verbose boot global variable pointer
170 | */
171 | uint8_t *gIOFBVerboseBootPtr {nullptr};
172 |
173 | /**
174 | * Original IGPU PCI Config readers
175 | */
176 | WIOKit::t_PCIConfigRead16 orgConfigRead16 {nullptr};
177 | WIOKit::t_PCIConfigRead32 orgConfigRead32 {nullptr};
178 |
179 | /**
180 | * Original AppleGraphicsDevicePolicy start handler
181 | */
182 | mach_vm_address_t orgGraphicsPolicyStart {0};
183 |
184 | /**
185 | * Original AppleIntelPanel set display handler
186 | */
187 | mach_vm_address_t orgApplePanelSetDisplay {0};
188 |
189 | /**
190 | * vinfo presence status
191 | */
192 | bool applePanelDisplaySet {false};
193 |
194 | /**
195 | * vinfo presence status
196 | */
197 | bool gotConsoleVinfo {false};
198 |
199 | /**
200 | * Device identification spoofing for IGPU
201 | */
202 | bool hasIgpuSpoof {false};
203 |
204 | /**
205 | * Device identification spoofing for GFX0
206 | */
207 | bool hasGfxSpoof {false};
208 |
209 | /**
210 | * Maximum GFX naming index (due to ACPI name restrictions)
211 | */
212 | static constexpr uint8_t MaxExternalGfxIndex {9};
213 |
214 | /**
215 | * GPU index used for GFXx naming in IORegistry
216 | * Must be single digits (i.e. 0~9 inclusive).
217 | */
218 | uint8_t currentExternalGfxIndex {0};
219 |
220 | /**
221 | * Maximum GFX slot naming index
222 | * Should be 1~4 to display properly in NVIDIA panel.
223 | * However, we permit more to match external GFX naming.
224 | */
225 | static constexpr uint8_t MaxExternalSlotIndex {10};
226 |
227 | /**
228 | * GPU index used for AAPL,slot-name naming in IORegistry
229 | * Should be 1~4 to display properly in NVIDIA panel.
230 | */
231 | uint8_t currentExternalSlotIndex {1};
232 |
233 | /**
234 | * AppleGraphicsDisplayPolicy modifications if applicable.
235 | *
236 | * AGDP_NONE no modifications
237 | * AGDP_DETECT detect on firmware vendor and hardware installed
238 | * AGDP_VIT9696 null config string size at strcmp
239 | * AGDP_PIKERA board-id -> board-ix replace
240 | * AGDP_CFGMAP add board-id with none to ConfigMap
241 | * SET bit is used to distinguish from agpmod=detect.
242 | */
243 | enum GraphicsDisplayPolicyMod {
244 | AGDP_SET = 0x8000,
245 | AGDP_NONE_SET = AGDP_SET | 0,
246 | AGDP_DETECT = 1,
247 | AGDP_DETECT_SET = AGDP_SET | AGDP_DETECT,
248 | AGDP_VIT9696 = 2,
249 | AGDP_PIKERA = 4,
250 | AGDP_CFGMAP = 8,
251 | AGDP_PATCHES = AGDP_VIT9696 | AGDP_PIKERA | AGDP_CFGMAP
252 | };
253 |
254 | /**
255 | * Current AppleGraphicsDisplayPolicy modifications.
256 | */
257 | int graphicsDisplayPolicyMod {AGDP_DETECT};
258 |
259 | /**
260 | * Apply pre-kext patches and setup the configuration
261 | *
262 | * @param patcher KernelPatcher instance
263 | */
264 | void processKernel(KernelPatcher &patcher);
265 |
266 | /**
267 | * Patch kext if needed and prepare other patches
268 | *
269 | * @param patcher KernelPatcher instance
270 | * @param index kinfo handle
271 | * @param address kinfo load address
272 | * @param size kinfo memory size
273 | */
274 | void processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size);
275 |
276 | /**
277 | * Apply builtin GPU properties and renamings
278 | *
279 | * @param device IGPU device
280 | * @param info device information
281 | */
282 | void processBuiltinProperties(IORegistryEntry *device, DeviceInfo *info);
283 |
284 | /**
285 | * Apply external GPU properties and renamings
286 | *
287 | * @param device GFX0 device
288 | * @param info device information
289 | */
290 | void processExternalProperties(IORegistryEntry *device, DeviceInfo *info, uint32_t vendor);
291 |
292 | /**
293 | * Apply IMEI properties and renamings
294 | *
295 | * @param device GFX0 device
296 | * @param info device information
297 | */
298 | void processManagementEngineProperties(IORegistryEntry *imei);
299 |
300 | /**
301 | * Parse AppleGraphicsDevicePolicy (AGDP) patch configuration
302 | *
303 | * @param patcher KernelPatcher instance
304 | * @param address agdp load address
305 | * @param size agdp memory size
306 | */
307 | void processGraphicsPolicyStr(const char *agdp);
308 |
309 | /**
310 | * Apply AppleGraphicsDevicePolicy (AGDP) patches if any
311 | *
312 | * @param patcher KernelPatcher instance
313 | * @param address agdp load address
314 | * @param size agdp memory size
315 | */
316 | void processGraphicsPolicyMods(KernelPatcher &patcher, mach_vm_address_t address, size_t size);
317 |
318 | /**
319 | * Check whether the graphics policy modification patches are required
320 | *
321 | * @param info device information
322 | *
323 | * @return true if we should continue
324 | */
325 | bool isGraphicsPolicyModRequired(DeviceInfo *info);
326 |
327 | /**
328 | * Attempts to find a printable name of an Intel GPU
329 | *
330 | * @param dev devide-id
331 | * @param fakeId fake devide-id
332 | *
333 | * @return autodetected GPU name or nullptr
334 | */
335 | const char *getIntelModel(uint32_t dev, uint32_t &fakeId);
336 |
337 | /**
338 | * Attempts to find a printable name of a Radeon GPU
339 | *
340 | * @param dev devide-id
341 | * @param rev revision-id
342 | * @param subven subsystem-vendor-id
343 | * @param sub susbsytem-id
344 | *
345 | * @return autodetected GPU name or nullptr
346 | */
347 | const char *getRadeonModel(uint16_t dev, uint16_t rev, uint16_t subven, uint16_t sub);
348 |
349 | /**
350 | * IGPU PCI Config device-id faking wrappers
351 | */
352 | static uint16_t wrapConfigRead16(IORegistryEntry *service, uint32_t space, uint8_t offset);
353 | static uint32_t wrapConfigRead32(IORegistryEntry *service, uint32_t space, uint8_t offset);
354 |
355 | /**
356 | * IOFramebuffer initialisation wrapper used for screen distortion fixes
357 | *
358 | * @param fb framebuffer instance
359 | */
360 | static void wrapFramebufferInit(IOFramebuffer *fb);
361 |
362 | /**
363 | * wrapper for function that only return zero
364 | *
365 | */
366 | static size_t wrapFunctionReturnZero();
367 |
368 | /**
369 | * AppleGraphicsDevicePolicy start wrapper used for black screen fixes in AGDP_CFGMAP mode
370 | *
371 | * @param that agdp instance
372 | * @param provider agdp provider
373 | *
374 | * @return agdp start status
375 | */
376 | static bool wrapGraphicsPolicyStart(IOService *that, IOService *provider);
377 |
378 | /**
379 | * AppleIntelPanel start wrapper used for extra panel injection
380 | *
381 | * @param that backlight panel instance
382 | * @param display backlight panel display
383 | *
384 | * @return backlight panel start status
385 | */
386 | static bool wrapApplePanelSetDisplay(IOService *that, IODisplay *display);
387 | };
388 |
389 | #endif /* kern_weg_hpp */
390 |
--------------------------------------------------------------------------------