├── .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 | --------------------------------------------------------------------------------