├── .github └── workflows │ └── main.yml ├── .gitignore ├── AirportBrcmFixup.xcodeproj └── project.pbxproj ├── AirportBrcmFixup ├── Info.plist ├── kern_brcmfx.cpp ├── kern_brcmfx.hpp ├── kern_config.hpp ├── kern_fakebrcm.cpp ├── kern_fakebrcm.hpp ├── kern_misc.hpp └── kern_start.cpp ├── Changelog.md ├── LICENSE.txt ├── README.md └── Resources ├── AirPortBrcm4360_Injector.kext └── Contents │ └── Info.plist └── AirPortBrcmNIC_Injector.kext └── Contents └── Info.plist /.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@v3 21 | - uses: actions/checkout@v3 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@v3 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@e74ff71f7d8a4c4745b560a485cc5fdb9b5b999d 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@v3 56 | - uses: actions/checkout@v3 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 AirportBrcmFixup -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 AirportBrcmFixup -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@v3 78 | - uses: actions/checkout@v3 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 | xcuserdata 5 | xcshareddata 6 | project.xcworkspace 7 | /MacKernelSDK 8 | -------------------------------------------------------------------------------- /AirportBrcmFixup.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1C748C2D1C21952C0024EED2 /* kern_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C748C2C1C21952C0024EED2 /* kern_start.cpp */; }; 11 | CE405ED91E4A080700AA0B3D /* plugin_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE405ED81E4A080700AA0B3D /* plugin_start.cpp */; }; 12 | CE8DA0A42517CE8B008C44E8 /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE8DA0A32517CE8B008C44E8 /* libkmod.a */; }; 13 | F641B3981F33857B009B3996 /* kern_misc.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F641B3971F33857B009B3996 /* kern_misc.hpp */; }; 14 | F660AAED24BA176D00BF749E /* AirPortBrcm4360_Injector.kext in Embed PlugIns */ = {isa = PBXBuildFile; fileRef = F660AAEB24BA176D00BF749E /* AirPortBrcm4360_Injector.kext */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 15 | F660AAEE24BA176D00BF749E /* AirPortBrcmNIC_Injector.kext in Embed PlugIns */ = {isa = PBXBuildFile; fileRef = F660AAEC24BA176D00BF749E /* AirPortBrcmNIC_Injector.kext */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 16 | F67C73C61E68AD890061CB0A /* kern_config.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F67C73C51E68AD890061CB0A /* kern_config.hpp */; }; 17 | F6C535E81E60963800A3A34B /* kern_brcmfx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6C535E61E60963800A3A34B /* kern_brcmfx.cpp */; }; 18 | F6C535E91E60963800A3A34B /* kern_brcmfx.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F6C535E71E60963800A3A34B /* kern_brcmfx.hpp */; }; 19 | F6D165611F2F86090022B27D /* kern_fakebrcm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6D1655F1F2F86090022B27D /* kern_fakebrcm.cpp */; }; 20 | F6D165621F2F86090022B27D /* kern_fakebrcm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F6D165601F2F86090022B27D /* kern_fakebrcm.hpp */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXCopyFilesBuildPhase section */ 24 | F660AAEF24BA176D00BF749E /* Embed PlugIns */ = { 25 | isa = PBXCopyFilesBuildPhase; 26 | buildActionMask = 2147483647; 27 | dstPath = ""; 28 | dstSubfolderSpec = 13; 29 | files = ( 30 | F660AAEE24BA176D00BF749E /* AirPortBrcmNIC_Injector.kext in Embed PlugIns */, 31 | F660AAED24BA176D00BF749E /* AirPortBrcm4360_Injector.kext in Embed PlugIns */, 32 | ); 33 | name = "Embed PlugIns"; 34 | runOnlyForDeploymentPostprocessing = 0; 35 | }; 36 | /* End PBXCopyFilesBuildPhase section */ 37 | 38 | /* Begin PBXFileReference section */ 39 | 1C748C271C21952C0024EED2 /* AirportBrcmFixup.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirportBrcmFixup.kext; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | 1C748C2C1C21952C0024EED2 /* kern_start.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = kern_start.cpp; sourceTree = ""; }; 41 | 1C748C2E1C21952C0024EED2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 42 | 1CF01C901C8CF97F002DCEA3 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 43 | 1CF01C921C8CF997002DCEA3 /* Changelog.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Changelog.md; sourceTree = ""; }; 44 | 1CF01C931C8DF02E002DCEA3 /* LICENSE.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; }; 45 | CE405EBA1E49DD7100AA0B3D /* kern_compression.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_compression.hpp; sourceTree = ""; }; 46 | CE405EBB1E49DD7100AA0B3D /* kern_disasm.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_disasm.hpp; sourceTree = ""; }; 47 | CE405EBC1E49DD7100AA0B3D /* kern_file.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_file.hpp; sourceTree = ""; }; 48 | CE405EBD1E49DD7100AA0B3D /* kern_iokit.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_iokit.hpp; sourceTree = ""; }; 49 | CE405EBE1E49DD7100AA0B3D /* kern_mach.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_mach.hpp; sourceTree = ""; }; 50 | CE405EBF1E49DD7100AA0B3D /* kern_patcher.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_patcher.hpp; sourceTree = ""; }; 51 | CE405EC01E49DD7100AA0B3D /* kern_policy.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_policy.hpp; sourceTree = ""; }; 52 | CE405EC31E49DD7100AA0B3D /* kern_user.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_user.hpp; sourceTree = ""; }; 53 | CE405EC41E49DD7100AA0B3D /* kern_util.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_util.hpp; sourceTree = ""; }; 54 | CE405ECF1E49EC9100AA0B3D /* kern_config.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = kern_config.hpp; sourceTree = ""; }; 55 | CE405ED21E49F9FC00AA0B3D /* kern_api.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_api.hpp; sourceTree = ""; }; 56 | CE405ED81E4A080700AA0B3D /* plugin_start.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = plugin_start.cpp; sourceTree = ""; }; 57 | CE405EDA1E4A080F00AA0B3D /* plugin_start.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = plugin_start.hpp; sourceTree = ""; }; 58 | CE8DA0A32517CE8B008C44E8 /* libkmod.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libkmod.a; path = ../Lilu/MacKernelSDK/Library/x86_64/libkmod.a; sourceTree = ""; }; 59 | F641B3971F33857B009B3996 /* kern_misc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = kern_misc.hpp; sourceTree = ""; }; 60 | F660AAEB24BA176D00BF749E /* AirPortBrcm4360_Injector.kext */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.kernel-extension"; name = AirPortBrcm4360_Injector.kext; path = Resources/AirPortBrcm4360_Injector.kext; sourceTree = ""; }; 61 | F660AAEC24BA176D00BF749E /* AirPortBrcmNIC_Injector.kext */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.kernel-extension"; name = AirPortBrcmNIC_Injector.kext; path = Resources/AirPortBrcmNIC_Injector.kext; sourceTree = ""; }; 62 | F67C73C51E68AD890061CB0A /* kern_config.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = kern_config.hpp; sourceTree = ""; }; 63 | F6C535E61E60963800A3A34B /* kern_brcmfx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kern_brcmfx.cpp; sourceTree = ""; usesTabs = 1; }; 64 | F6C535E71E60963800A3A34B /* kern_brcmfx.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = kern_brcmfx.hpp; sourceTree = ""; usesTabs = 1; }; 65 | F6D1655F1F2F86090022B27D /* kern_fakebrcm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kern_fakebrcm.cpp; sourceTree = ""; usesTabs = 1; }; 66 | F6D165601F2F86090022B27D /* kern_fakebrcm.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = kern_fakebrcm.hpp; sourceTree = ""; }; 67 | /* End PBXFileReference section */ 68 | 69 | /* Begin PBXFrameworksBuildPhase section */ 70 | 1C748C231C21952C0024EED2 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | CE8DA0A42517CE8B008C44E8 /* libkmod.a in Frameworks */, 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | /* End PBXFrameworksBuildPhase section */ 79 | 80 | /* Begin PBXGroup section */ 81 | 1C748C1D1C21952C0024EED2 = { 82 | isa = PBXGroup; 83 | children = ( 84 | 1CF01C911C8CF982002DCEA3 /* Docs */, 85 | 1C748C291C21952C0024EED2 /* AirportBrcmFixup */, 86 | CE405EC81E49DD7B00AA0B3D /* SDK */, 87 | 1C748C281C21952C0024EED2 /* Products */, 88 | F61DF88C24BA12AF007F9208 /* Frameworks */, 89 | ); 90 | sourceTree = ""; 91 | }; 92 | 1C748C281C21952C0024EED2 /* Products */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | 1C748C271C21952C0024EED2 /* AirportBrcmFixup.kext */, 96 | ); 97 | name = Products; 98 | sourceTree = ""; 99 | }; 100 | 1C748C291C21952C0024EED2 /* AirportBrcmFixup */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | F641B3971F33857B009B3996 /* kern_misc.hpp */, 104 | F6D1655F1F2F86090022B27D /* kern_fakebrcm.cpp */, 105 | F6D165601F2F86090022B27D /* kern_fakebrcm.hpp */, 106 | F67C73C51E68AD890061CB0A /* kern_config.hpp */, 107 | F6C535E61E60963800A3A34B /* kern_brcmfx.cpp */, 108 | F6C535E71E60963800A3A34B /* kern_brcmfx.hpp */, 109 | 1C748C2C1C21952C0024EED2 /* kern_start.cpp */, 110 | 1C748C2E1C21952C0024EED2 /* Info.plist */, 111 | ); 112 | path = AirportBrcmFixup; 113 | sourceTree = ""; 114 | }; 115 | 1CF01C911C8CF982002DCEA3 /* Docs */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 1CF01C901C8CF97F002DCEA3 /* README.md */, 119 | 1CF01C931C8DF02E002DCEA3 /* LICENSE.txt */, 120 | 1CF01C921C8CF997002DCEA3 /* Changelog.md */, 121 | ); 122 | name = Docs; 123 | sourceTree = ""; 124 | }; 125 | CE405EB91E49DD7100AA0B3D /* Headers */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | CE405ED21E49F9FC00AA0B3D /* kern_api.hpp */, 129 | CE405ECF1E49EC9100AA0B3D /* kern_config.hpp */, 130 | CE405EBA1E49DD7100AA0B3D /* kern_compression.hpp */, 131 | CE405EBB1E49DD7100AA0B3D /* kern_disasm.hpp */, 132 | CE405EBC1E49DD7100AA0B3D /* kern_file.hpp */, 133 | CE405EBD1E49DD7100AA0B3D /* kern_iokit.hpp */, 134 | CE405EBE1E49DD7100AA0B3D /* kern_mach.hpp */, 135 | CE405EBF1E49DD7100AA0B3D /* kern_patcher.hpp */, 136 | CE405EC01E49DD7100AA0B3D /* kern_policy.hpp */, 137 | CE405EC31E49DD7100AA0B3D /* kern_user.hpp */, 138 | CE405EC41E49DD7100AA0B3D /* kern_util.hpp */, 139 | CE405EDA1E4A080F00AA0B3D /* plugin_start.hpp */, 140 | ); 141 | name = Headers; 142 | path = Lilu.kext/Contents/Resources/Headers; 143 | sourceTree = SOURCE_ROOT; 144 | }; 145 | CE405EC51E49DD7100AA0B3D /* Library */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | CE405ED81E4A080700AA0B3D /* plugin_start.cpp */, 149 | ); 150 | name = Library; 151 | path = Lilu.kext/Contents/Resources/Library; 152 | sourceTree = SOURCE_ROOT; 153 | }; 154 | CE405EC81E49DD7B00AA0B3D /* SDK */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | CE405EB91E49DD7100AA0B3D /* Headers */, 158 | CE405EC51E49DD7100AA0B3D /* Library */, 159 | ); 160 | name = SDK; 161 | sourceTree = ""; 162 | }; 163 | F61DF88C24BA12AF007F9208 /* Frameworks */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | CE8DA0A32517CE8B008C44E8 /* libkmod.a */, 167 | F660AAEB24BA176D00BF749E /* AirPortBrcm4360_Injector.kext */, 168 | F660AAEC24BA176D00BF749E /* AirPortBrcmNIC_Injector.kext */, 169 | ); 170 | name = Frameworks; 171 | sourceTree = ""; 172 | }; 173 | /* End PBXGroup section */ 174 | 175 | /* Begin PBXHeadersBuildPhase section */ 176 | 1C748C241C21952C0024EED2 /* Headers */ = { 177 | isa = PBXHeadersBuildPhase; 178 | buildActionMask = 2147483647; 179 | files = ( 180 | F67C73C61E68AD890061CB0A /* kern_config.hpp in Headers */, 181 | F6D165621F2F86090022B27D /* kern_fakebrcm.hpp in Headers */, 182 | F641B3981F33857B009B3996 /* kern_misc.hpp in Headers */, 183 | F6C535E91E60963800A3A34B /* kern_brcmfx.hpp in Headers */, 184 | ); 185 | runOnlyForDeploymentPostprocessing = 0; 186 | }; 187 | /* End PBXHeadersBuildPhase section */ 188 | 189 | /* Begin PBXNativeTarget section */ 190 | 1C748C261C21952C0024EED2 /* AirportBrcmFixup */ = { 191 | isa = PBXNativeTarget; 192 | buildConfigurationList = 1C748C311C21952C0024EED2 /* Build configuration list for PBXNativeTarget "AirportBrcmFixup" */; 193 | buildPhases = ( 194 | 1C748C221C21952C0024EED2 /* Sources */, 195 | 1C748C231C21952C0024EED2 /* Frameworks */, 196 | 1C748C241C21952C0024EED2 /* Headers */, 197 | 1C748C251C21952C0024EED2 /* Resources */, 198 | F660AAEF24BA176D00BF749E /* Embed PlugIns */, 199 | F6AC609A2052C61300376609 /* Archive */, 200 | ); 201 | buildRules = ( 202 | ); 203 | dependencies = ( 204 | ); 205 | name = AirportBrcmFixup; 206 | productName = AirportBrcmFixup; 207 | productReference = 1C748C271C21952C0024EED2 /* AirportBrcmFixup.kext */; 208 | productType = "com.apple.product-type.kernel-extension"; 209 | }; 210 | /* End PBXNativeTarget section */ 211 | 212 | /* Begin PBXProject section */ 213 | 1C748C1E1C21952C0024EED2 /* Project object */ = { 214 | isa = PBXProject; 215 | attributes = { 216 | LastUpgradeCheck = 1200; 217 | ORGANIZATIONNAME = vit9696; 218 | TargetAttributes = { 219 | 1C748C261C21952C0024EED2 = { 220 | CreatedOnToolsVersion = 7.2; 221 | ProvisioningStyle = Manual; 222 | }; 223 | }; 224 | }; 225 | buildConfigurationList = 1C748C211C21952C0024EED2 /* Build configuration list for PBXProject "AirportBrcmFixup" */; 226 | compatibilityVersion = "Xcode 3.2"; 227 | developmentRegion = en; 228 | hasScannedForEncodings = 0; 229 | knownRegions = ( 230 | en, 231 | Base, 232 | ); 233 | mainGroup = 1C748C1D1C21952C0024EED2; 234 | productRefGroup = 1C748C281C21952C0024EED2 /* Products */; 235 | projectDirPath = ""; 236 | projectRoot = ""; 237 | targets = ( 238 | 1C748C261C21952C0024EED2 /* AirportBrcmFixup */, 239 | ); 240 | }; 241 | /* End PBXProject section */ 242 | 243 | /* Begin PBXResourcesBuildPhase section */ 244 | 1C748C251C21952C0024EED2 /* Resources */ = { 245 | isa = PBXResourcesBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | /* End PBXResourcesBuildPhase section */ 252 | 253 | /* Begin PBXShellScriptBuildPhase section */ 254 | F6AC609A2052C61300376609 /* Archive */ = { 255 | isa = PBXShellScriptBuildPhase; 256 | buildActionMask = 2147483647; 257 | files = ( 258 | ); 259 | inputPaths = ( 260 | ); 261 | name = Archive; 262 | outputPaths = ( 263 | ); 264 | runOnlyForDeploymentPostprocessing = 0; 265 | shellPath = /bin/sh; 266 | shellScript = "cd \"${TARGET_BUILD_DIR}\"\n\ndist=(\"$FULL_PRODUCT_NAME\")\nif [ -d \"$DWARF_DSYM_FILE_NAME\" ]; then dist+=(\"$DWARF_DSYM_FILE_NAME\"); fi\n\narchive=\"${PRODUCT_NAME}-${MODULE_VERSION}-$(echo $CONFIGURATION | tr /a-z/ /A-Z/).zip\"\nrm -rf *.zip\nif [ \"$CONFIGURATION\" == \"Release\" ]; then strip -x -T \"${EXECUTABLE_PATH}\"; fi\nzip -qry -FS \"${archive}\" \"${dist[@]}\"\n"; 267 | }; 268 | /* End PBXShellScriptBuildPhase section */ 269 | 270 | /* Begin PBXSourcesBuildPhase section */ 271 | 1C748C221C21952C0024EED2 /* Sources */ = { 272 | isa = PBXSourcesBuildPhase; 273 | buildActionMask = 2147483647; 274 | files = ( 275 | F6D165611F2F86090022B27D /* kern_fakebrcm.cpp in Sources */, 276 | CE405ED91E4A080700AA0B3D /* plugin_start.cpp in Sources */, 277 | F6C535E81E60963800A3A34B /* kern_brcmfx.cpp in Sources */, 278 | 1C748C2D1C21952C0024EED2 /* kern_start.cpp in Sources */, 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | }; 282 | /* End PBXSourcesBuildPhase section */ 283 | 284 | /* Begin XCBuildConfiguration section */ 285 | 1C748C2F1C21952C0024EED2 /* Debug */ = { 286 | isa = XCBuildConfiguration; 287 | buildSettings = { 288 | ALWAYS_SEARCH_USER_PATHS = NO; 289 | ARCHS = x86_64; 290 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 291 | CLANG_CXX_LANGUAGE_STANDARD = "c++1y"; 292 | CLANG_CXX_LIBRARY = "libc++"; 293 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 294 | CLANG_WARN_BOOL_CONVERSION = YES; 295 | CLANG_WARN_COMMA = YES; 296 | CLANG_WARN_CONSTANT_CONVERSION = YES; 297 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 298 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 299 | CLANG_WARN_EMPTY_BODY = YES; 300 | CLANG_WARN_ENUM_CONVERSION = YES; 301 | CLANG_WARN_INFINITE_RECURSION = YES; 302 | CLANG_WARN_INT_CONVERSION = YES; 303 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 304 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 305 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 306 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 307 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 308 | CLANG_WARN_STRICT_PROTOTYPES = YES; 309 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 310 | CLANG_WARN_UNREACHABLE_CODE = YES; 311 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 312 | DEBUG_INFORMATION_FORMAT = dwarf; 313 | ENABLE_STRICT_OBJC_MSGSEND = YES; 314 | ENABLE_TESTABILITY = YES; 315 | GCC_C_LANGUAGE_STANDARD = c11; 316 | GCC_NO_COMMON_BLOCKS = YES; 317 | GCC_OPTIMIZATION_LEVEL = 0; 318 | GCC_PREPROCESSOR_DEFINITIONS = ( 319 | "DEBUG=1", 320 | "$(inherited)", 321 | ); 322 | GCC_SYMBOLS_PRIVATE_EXTERN = YES; 323 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 324 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 325 | GCC_WARN_UNDECLARED_SELECTOR = YES; 326 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 327 | GCC_WARN_UNUSED_FUNCTION = YES; 328 | GCC_WARN_UNUSED_VARIABLE = YES; 329 | KERNEL_EXTENSION_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; 330 | KERNEL_FRAMEWORK_HEADERS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; 331 | MACOSX_DEPLOYMENT_TARGET = 10.8; 332 | ONLY_ACTIVE_ARCH = YES; 333 | SDKROOT = macosx; 334 | }; 335 | name = Debug; 336 | }; 337 | 1C748C301C21952C0024EED2 /* Release */ = { 338 | isa = XCBuildConfiguration; 339 | buildSettings = { 340 | ALWAYS_SEARCH_USER_PATHS = NO; 341 | ARCHS = x86_64; 342 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 343 | CLANG_CXX_LANGUAGE_STANDARD = "c++1y"; 344 | CLANG_CXX_LIBRARY = "libc++"; 345 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 346 | CLANG_WARN_BOOL_CONVERSION = YES; 347 | CLANG_WARN_COMMA = YES; 348 | CLANG_WARN_CONSTANT_CONVERSION = YES; 349 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 350 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 351 | CLANG_WARN_EMPTY_BODY = YES; 352 | CLANG_WARN_ENUM_CONVERSION = YES; 353 | CLANG_WARN_INFINITE_RECURSION = YES; 354 | CLANG_WARN_INT_CONVERSION = YES; 355 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 356 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 357 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 358 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 359 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 360 | CLANG_WARN_STRICT_PROTOTYPES = YES; 361 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 362 | CLANG_WARN_UNREACHABLE_CODE = YES; 363 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 364 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 365 | ENABLE_STRICT_OBJC_MSGSEND = YES; 366 | GCC_C_LANGUAGE_STANDARD = c11; 367 | GCC_NO_COMMON_BLOCKS = YES; 368 | GCC_OPTIMIZATION_LEVEL = 3; 369 | GCC_SYMBOLS_PRIVATE_EXTERN = YES; 370 | GCC_UNROLL_LOOPS = YES; 371 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 372 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 373 | GCC_WARN_UNDECLARED_SELECTOR = YES; 374 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 375 | GCC_WARN_UNUSED_FUNCTION = YES; 376 | GCC_WARN_UNUSED_VARIABLE = YES; 377 | KERNEL_EXTENSION_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; 378 | KERNEL_FRAMEWORK_HEADERS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; 379 | MACOSX_DEPLOYMENT_TARGET = 10.8; 380 | SDKROOT = macosx; 381 | }; 382 | name = Release; 383 | }; 384 | 1C748C321C21952C0024EED2 /* Debug */ = { 385 | isa = XCBuildConfiguration; 386 | buildSettings = { 387 | CLANG_ENABLE_OBJC_WEAK = YES; 388 | CODE_SIGN_IDENTITY = ""; 389 | CODE_SIGN_STYLE = Manual; 390 | COPY_PHASE_STRIP = NO; 391 | CURRENT_PROJECT_VERSION = "$(MODULE_VERSION)"; 392 | DEPLOYMENT_POSTPROCESSING = YES; 393 | GCC_ENABLE_FLOATING_POINT_LIBRARY_CALLS = NO; 394 | GCC_ENABLE_KERNEL_DEVELOPMENT = NO; 395 | GCC_GENERATE_DEBUGGING_SYMBOLS = NO; 396 | GCC_PREPROCESSOR_DEFINITIONS = ( 397 | "MODULE_VERSION=$(MODULE_VERSION)", 398 | "PRODUCT_NAME=$(PRODUCT_NAME)", 399 | "$(inherited)", 400 | ); 401 | HEADER_SEARCH_PATHS = "${PROJECT_DIR}/Lilu.kext/Contents/Resources"; 402 | INFOPLIST_FILE = AirportBrcmFixup/Info.plist; 403 | LIBRARY_SEARCH_PATHS = ( 404 | "$(inherited)", 405 | "$(PROJECT_DIR)/MacKernelSDK/Library/x86_64", 406 | ); 407 | MACOSX_DEPLOYMENT_TARGET = 10.8; 408 | MODULE_NAME = as.lvs1974.AirportBrcmFixup; 409 | MODULE_START = "$(PRODUCT_NAME)_kern_start"; 410 | MODULE_STOP = "$(PRODUCT_NAME)_kern_stop"; 411 | MODULE_VERSION = 2.2.0; 412 | OTHER_CFLAGS = ( 413 | "-mmmx", 414 | "-msse", 415 | "-msse2", 416 | "-msse3", 417 | "-mfpmath=sse", 418 | "-mssse3", 419 | "-ftree-vectorize", 420 | "-fno-non-call-exceptions", 421 | "-fno-builtin", 422 | "-fno-asynchronous-unwind-tables", 423 | "-Wno-unknown-warning-option", 424 | "-Wno-ossharedptr-misuse", 425 | "-Wno-vla", 426 | ); 427 | OTHER_LDFLAGS = "-static"; 428 | PRODUCT_BUNDLE_IDENTIFIER = as.lvs1974.AirportBrcmFixup; 429 | PRODUCT_NAME = "$(TARGET_NAME)"; 430 | WRAPPER_EXTENSION = kext; 431 | }; 432 | name = Debug; 433 | }; 434 | 1C748C331C21952C0024EED2 /* Release */ = { 435 | isa = XCBuildConfiguration; 436 | buildSettings = { 437 | CLANG_ENABLE_OBJC_WEAK = YES; 438 | CODE_SIGN_IDENTITY = ""; 439 | CODE_SIGN_STYLE = Manual; 440 | CURRENT_PROJECT_VERSION = "$(MODULE_VERSION)"; 441 | DEAD_CODE_STRIPPING = YES; 442 | DEPLOYMENT_POSTPROCESSING = YES; 443 | GCC_ENABLE_FLOATING_POINT_LIBRARY_CALLS = NO; 444 | GCC_ENABLE_KERNEL_DEVELOPMENT = NO; 445 | GCC_GENERATE_DEBUGGING_SYMBOLS = YES; 446 | GCC_PREPROCESSOR_DEFINITIONS = ( 447 | "MODULE_VERSION=$(MODULE_VERSION)", 448 | "PRODUCT_NAME=$(PRODUCT_NAME)", 449 | ); 450 | HEADER_SEARCH_PATHS = "${PROJECT_DIR}/Lilu.kext/Contents/Resources"; 451 | INFOPLIST_FILE = AirportBrcmFixup/Info.plist; 452 | LIBRARY_SEARCH_PATHS = ( 453 | "$(inherited)", 454 | "$(PROJECT_DIR)/MacKernelSDK/Library/x86_64", 455 | ); 456 | LLVM_LTO = YES; 457 | MACOSX_DEPLOYMENT_TARGET = 10.8; 458 | MODULE_NAME = as.lvs1974.AirportBrcmFixup; 459 | MODULE_START = "$(PRODUCT_NAME)_kern_start"; 460 | MODULE_STOP = "$(PRODUCT_NAME)_kern_stop"; 461 | MODULE_VERSION = 2.2.0; 462 | OTHER_CFLAGS = ( 463 | "-mmmx", 464 | "-msse", 465 | "-msse2", 466 | "-msse3", 467 | "-mfpmath=sse", 468 | "-mssse3", 469 | "-ftree-vectorize", 470 | "-fno-non-call-exceptions", 471 | "-fno-builtin", 472 | "-fno-asynchronous-unwind-tables", 473 | "-Wno-unknown-warning-option", 474 | "-Wno-ossharedptr-misuse", 475 | "-Wno-vla", 476 | ); 477 | OTHER_LDFLAGS = "-static"; 478 | PRODUCT_BUNDLE_IDENTIFIER = as.lvs1974.AirportBrcmFixup; 479 | PRODUCT_NAME = "$(TARGET_NAME)"; 480 | STRIP_STYLE = "non-global"; 481 | WRAPPER_EXTENSION = kext; 482 | }; 483 | name = Release; 484 | }; 485 | /* End XCBuildConfiguration section */ 486 | 487 | /* Begin XCConfigurationList section */ 488 | 1C748C211C21952C0024EED2 /* Build configuration list for PBXProject "AirportBrcmFixup" */ = { 489 | isa = XCConfigurationList; 490 | buildConfigurations = ( 491 | 1C748C2F1C21952C0024EED2 /* Debug */, 492 | 1C748C301C21952C0024EED2 /* Release */, 493 | ); 494 | defaultConfigurationIsVisible = 0; 495 | defaultConfigurationName = Release; 496 | }; 497 | 1C748C311C21952C0024EED2 /* Build configuration list for PBXNativeTarget "AirportBrcmFixup" */ = { 498 | isa = XCConfigurationList; 499 | buildConfigurations = ( 500 | 1C748C321C21952C0024EED2 /* Debug */, 501 | 1C748C331C21952C0024EED2 /* Release */, 502 | ); 503 | defaultConfigurationIsVisible = 0; 504 | defaultConfigurationName = Release; 505 | }; 506 | /* End XCConfigurationList section */ 507 | }; 508 | rootObject = 1C748C1E1C21952C0024EED2 /* Project object */; 509 | } 510 | -------------------------------------------------------------------------------- /AirportBrcmFixup/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | KEXT 17 | CFBundleShortVersionString 18 | $(MODULE_VERSION) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(MODULE_VERSION) 23 | IOKitPersonalities 24 | 25 | as.lvs1974.AirportBrcmFixup 26 | 27 | CFBundleIdentifier 28 | $(PRODUCT_BUNDLE_IDENTIFIER) 29 | IOClass 30 | $(PRODUCT_NAME:rfc1034identifier) 31 | IOMatchCategory 32 | $(PRODUCT_NAME:rfc1034identifier) 33 | IOProviderClass 34 | IOResources 35 | IOResourceMatch 36 | IOKit 37 | 38 | as.lvs1974.FakeAirportBrcmFixup 39 | 40 | CFBundleIdentifier 41 | $(PRODUCT_BUNDLE_IDENTIFIER) 42 | IOClass 43 | FakeBrcm 44 | IOMatchCategory 45 | IODefaultMatchCategory 46 | IONameMatch 47 | 48 | pci14e4,43ba 49 | pci14e4,43a3 50 | pci14e4,43a0 51 | pci14e4,4331 52 | pci14e4,4353 53 | pci14e4,43b1 54 | pci14e4,43b2 55 | pci14e4,4357 56 | pci14e4,432b 57 | pci14e4,4311 58 | pci14e4,4312 59 | pci14e4,4313 60 | pci14e4,4318 61 | pci14e4,4319 62 | pci14e4,431a 63 | pci14e4,4320 64 | pci14e4,4324 65 | pci14e4,4325 66 | pci14e4,4328 67 | pci14e4,432c 68 | pci14e4,432d 69 | 70 | IOProbeScore 71 | 6000 72 | IOProviderClass 73 | IOPCIDevice 74 | TruePowerOff 75 | 76 | 77 | 78 | NSHumanReadableCopyright 79 | Copyright © 2017 lvs1974. All rights reserved. 80 | OSBundleCompatibleVersion 81 | 1.0 82 | OSBundleLibraries 83 | 84 | as.vit9696.Lilu 85 | 1.2.6 86 | com.apple.iokit.IOPCIFamily 87 | 2.7 88 | com.apple.kpi.bsd 89 | 12.0.0 90 | com.apple.kpi.dsep 91 | 12.0.0 92 | com.apple.kpi.iokit 93 | 12.0.0 94 | com.apple.kpi.libkern 95 | 12.0.0 96 | com.apple.kpi.mach 97 | 12.0.0 98 | com.apple.kpi.unsupported 99 | 12.0.0 100 | 101 | OSBundleRequired 102 | Network-Root 103 | 104 | 105 | -------------------------------------------------------------------------------- /AirportBrcmFixup/kern_brcmfx.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // kern_brcmfx.cpp 3 | // AirportBrcmFixup 4 | // 5 | // Copyright © 2017 lvs1974. All rights reserved. 6 | // 7 | 8 | #include "kern_api.hpp" 9 | #include "kern_config.hpp" 10 | #include "kern_brcmfx.hpp" 11 | #include "kern_fakebrcm.hpp" 12 | 13 | #include 14 | #include 15 | 16 | // Only used in apple-driven callbacks 17 | static BRCMFX *callbackBRCMFX {nullptr}; 18 | static const char *kextIOPCIFamilyPath = "/System/Library/Extensions/IOPCIFamily.kext/IOPCIFamily"; 19 | static const size_t kextListSize {MaxServices+1}; 20 | static bool kext_handled[kextListSize] {}; 21 | 22 | static KernelPatcher::KextInfo kextList[kextListSize] { 23 | { idList[AirPort_BrcmNIC_MFG], binList[AirPort_BrcmNIC_MFG], 1, {true}, {}, KernelPatcher::KextInfo::Unloaded }, 24 | { idList[AirPort_Brcm4360], binList[AirPort_Brcm4360], 1, {true}, {}, KernelPatcher::KextInfo::Unloaded }, 25 | { idList[AirPort_BrcmNIC], binList[AirPort_BrcmNIC], 2, {true}, {}, KernelPatcher::KextInfo::Unloaded }, 26 | { idList[AirPort_Brcm4331], binList[AirPort_Brcm4331], 1, {true}, {}, KernelPatcher::KextInfo::Unloaded }, 27 | {"com.apple.iokit.IOPCIFamily", &kextIOPCIFamilyPath, 1, {true}, {}, KernelPatcher::KextInfo::Unloaded } 28 | }; 29 | 30 | //============================================================================== 31 | 32 | bool BRCMFX::init() 33 | { 34 | DBGLOG("BRCMFX", "init method is called"); 35 | callbackBRCMFX = this; 36 | 37 | lilu.onPatcherLoadForce( 38 | [](void *user, KernelPatcher &patcher) { 39 | callbackBRCMFX->processKernel(patcher); 40 | }, this); 41 | 42 | for (int i=0; iprocessKext(patcher, index, address, size); 51 | }, this); 52 | 53 | 54 | return true; 55 | } 56 | 57 | //============================================================================== 58 | 59 | void BRCMFX::deinit() 60 | { 61 | } 62 | 63 | //============================================================================== 64 | 65 | template 66 | bool BRCMFX::checkBoardId(void *that, const char *boardID) 67 | { 68 | if (index == AirPort_Brcm4360 && callbackBRCMFX && callbackBRCMFX->cpmChanSwitchWhitelist) 69 | { 70 | const char **cpmChanSwitchWhitelist = callbackBRCMFX->cpmChanSwitchWhitelist; 71 | while (*cpmChanSwitchWhitelist) 72 | { 73 | if (boardID == *cpmChanSwitchWhitelist) 74 | { 75 | DBGLOG("BRCMFX", "checkBoardId is called with boardID from cpmChanSwitchWhitelist: %s", boardID); 76 | return false; 77 | } 78 | cpmChanSwitchWhitelist++; 79 | } 80 | } 81 | return true; 82 | } 83 | 84 | //============================================================================== 85 | 86 | const OSSymbol* BRCMFX::newVendorString(void) 87 | { 88 | DBGLOG("BRCMFX", "newVendorString is called"); 89 | return OSSymbol::withCString("Apple"); 90 | } 91 | 92 | //============================================================================== 93 | 94 | bool BRCMFX::wlc_wowl_enable(int64_t **a1) 95 | { 96 | DBGLOG("BRCMFX", "wlc_wowl_enable is called, change returned value to false"); 97 | return false; 98 | } 99 | 100 | //============================================================================== 101 | 102 | bool BRCMFX::wowCapablePlatform(void *that) 103 | { 104 | DBGLOG("BRCMFX", "wowCapablePlatform is called, change returned value to false"); 105 | return false; 106 | } 107 | 108 | //============================================================================== 109 | // 23 61 means '#' 'a', "#a" is universal for all countries 110 | // 55 53 -> US 111 | // 43 4e -> CN 112 | 113 | //============================================================================== 114 | 115 | template 116 | int64_t BRCMFX::wlc_set_countrycode_rev(int64_t a1, const char *country_code, int a3) 117 | { 118 | DBGLOG("BRCMFX", "wlc_set_countrycode_rev%ld is called, a3 = %d, country_code = %s", index, a3, country_code); 119 | 120 | const char *new_country_code = ADDPR(brcmfx_config).country_code; 121 | int64_t result = FunctionCast(wlc_set_countrycode_rev, callbackBRCMFX->orgWlcSetCountryCodeRev[index])(a1, new_country_code, -1); 122 | DBGLOG("BRCMFX", "country code is changed from %s to %s, result = %lld", country_code, new_country_code, result); 123 | IOSleep(300); 124 | 125 | return result; 126 | } 127 | 128 | //============================================================================== 129 | 130 | int64_t BRCMFX::wlc_set_countrycode_rev_4331(int64_t a1, int64_t a2, const char *country_code, int a4) 131 | { 132 | int index = AirPort_Brcm4331; 133 | DBGLOG("BRCMFX", "wlc_set_countrycode_rev_4331 is called, a4 = %d, country_code = %s", a4, country_code); 134 | 135 | const char *new_country_code = ADDPR(brcmfx_config).country_code; 136 | int64_t result = FunctionCast(wlc_set_countrycode_rev_4331, callbackBRCMFX->orgWlcSetCountryCodeRev[index])(a1, a2, new_country_code, -1); 137 | DBGLOG("BRCMFX", "country code is changed from %s to %s, result = %lld", country_code, new_country_code, result); 138 | IOSleep(300); 139 | 140 | return result; 141 | } 142 | 143 | 144 | //_si_pmu_fvco_pllreg (10.11 - 10.13) compares value stored at [rdi+0x3c] with 0xaa52. This value is a chip identificator: 43602, details: 145 | // https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-3.18/drivers/net/wireless/bcmdhd/include/bcmdevs.h#396 146 | // In 10.12 and earlier _si_pmu_fvco_pllreg will fail if the value stored at [rdi+0x3c] is not 0xaa52, driver won't be loaded 147 | 148 | template 149 | int64_t BRCMFX::siPmuFvcoPllreg(uint32_t *a1, int64_t a2, int64_t a3) 150 | { 151 | uint32_t original = a1[15]; 152 | a1[15] = 0xaa52; 153 | 154 | DBGLOG("BRCMFX", "siPmuFvcoPllreg%ld, original chip identificator = %04x", index, original); 155 | auto ret = FunctionCast(siPmuFvcoPllreg, callbackBRCMFX->orgSiPmuFvcoPllreg[index])(a1, a2, a3); 156 | 157 | a1[15] = original; 158 | 159 | return ret; 160 | } 161 | 162 | 163 | #ifdef DEBUG 164 | //============================================================================== 165 | 166 | template 167 | IOReturn BRCMFX::AirPort_BrcmNIC_setTX_NSS(void *that, OSObject *obj, apple80211_tx_nss_data *data) 168 | { 169 | auto result = FunctionCast(AirPort_BrcmNIC_setTX_NSS, callbackBRCMFX->orgAirPort_BrcmNIC_setTX_NSS[index])(that, obj, data); 170 | DBGLOG("BRCMFX", "AirPort_BrcmNIC::setTX_NSS: result = 0x%x, version = %d, nss = %d", result, data->version, data->nss); 171 | return result; 172 | } 173 | 174 | //============================================================================== 175 | 176 | template 177 | IOReturn BRCMFX::AirPort_BrcmNIC_getTX_NSS(void *that, OSObject *obj, apple80211_tx_nss_data *data) 178 | { 179 | auto result = FunctionCast(AirPort_BrcmNIC_getTX_NSS, callbackBRCMFX->orgAirPort_BrcmNIC_getTX_NSS[index])(that, obj, data); 180 | DBGLOG("BRCMFX", "AirPort_BrcmNIC::getTX_NSS: result = 0x%x, version = %d, ess = %d", result, data->version, data->nss); 181 | // if ((result == KERN_SUCCESS || result == KERN_RESOURCE_SHORTAGE) && data->nss == 1) 182 | // { 183 | // data->nss = 2; 184 | // DBGLOG("BRCMFX", "AirPort_BrcmNIC::getTX_NSS: version = %d, overrided nss = %d", data->version, data->nss); 185 | // result = KERN_SUCCESS; 186 | // } 187 | return result; 188 | } 189 | 190 | //============================================================================== 191 | 192 | template 193 | IOReturn BRCMFX::AirPort_BrcmNIC_getNSS(void *that, OSObject *obj, apple80211_nss_data *data) 194 | { 195 | auto result = FunctionCast(AirPort_BrcmNIC_getNSS, callbackBRCMFX->orgAirPort_BrcmNIC_getNSS[index])(that, obj, data); 196 | DBGLOG("BRCMFX", "AirPort_BrcmNIC::getNSS: result = 0x%x, version = %d, nss = %d", result, data->version, data->nss); 197 | // if ((result == KERN_SUCCESS || result == KERN_RESOURCE_SHORTAGE) && data->nss == 1) 198 | // { 199 | // data->nss = 2; 200 | // DBGLOG("BRCMFX", "AirPort_BrcmNIC::getNSS: version = %d, overrided nss = %d", data->version, data->nss); 201 | // result = KERN_SUCCESS; 202 | // } 203 | return result; 204 | } 205 | 206 | //============================================================================== 207 | 208 | template 209 | int64_t BRCMFX::wlc_ratespec_nss(int a1) 210 | { 211 | auto result = FunctionCast(wlc_ratespec_nss, callbackBRCMFX->orgWlcRatespecNss[index])(a1); 212 | DBGLOG("BRCMFX", "wlc_ratespec_nss: result = 0x%x, a1 = 0x%x", result, a1); 213 | return result; 214 | } 215 | #endif 216 | 217 | //============================================================================== 218 | 219 | bool BRCMFX::start(IOService* service, IOService* provider) 220 | { 221 | DBGLOG("BRCMFX", "start is called, service name is %s, provider name is %s", safeString(service->getName()), safeString(provider->getName())); 222 | ADDPR(brcmfx_config).readArguments(provider); 223 | 224 | int index = find_service_index(safeString(service->getName())); 225 | int brcmfx_driver = ADDPR(brcmfx_config).brcmfx_driver; 226 | 227 | bool disable_driver = (brcmfx_driver == -1 && index == AirPort_BrcmNIC_MFG) || (brcmfx_driver != -1 && brcmfx_driver != index); 228 | if (index < 0 || disable_driver) { 229 | DBGLOG("BRCMFX", "start: disable service %s", safeString(service->getName())); 230 | return false; 231 | } 232 | 233 | auto name = safeString(provider->getName()); 234 | 235 | // There could be only one ARPT 236 | if (!name || strcmp(name, "ARPT") != 0) 237 | WIOKit::renameDevice(provider, "ARPT"); 238 | 239 | PCIHookManager::hookProvider(provider); 240 | if (ADDPR(brcmfx_config).override_aspm && callbackBRCMFX->setASPMState) { 241 | IOReturn result = callbackBRCMFX->setASPMState(provider, provider, ADDPR(brcmfx_config).brcmfx_aspm); 242 | if (result != KERN_SUCCESS) 243 | SYSLOG("BRCMFX", "setASPMState has failed with code 0x%x", result); 244 | } 245 | 246 | static _Atomic(bool) start_called[MaxServices] = {}; 247 | bool result = false; 248 | if (!start_called[index]) 249 | { 250 | start_called[index] = true; 251 | IOSleep(ADDPR(brcmfx_config).start_delay); 252 | result = FunctionCast(start, callbackBRCMFX->orgStart[index])(service, provider); 253 | DBGLOG("BRCMFX", "start is finished with result %d", result); 254 | if (result) 255 | callbackBRCMFX->atLeastOneServiceStarted = true; 256 | } 257 | else 258 | { 259 | SYSLOG("BRCMFX", "start was already called for service %s", safeString(service->getName()), safeString(provider->getName())); 260 | } 261 | return result; 262 | } 263 | 264 | //============================================================================== 265 | 266 | IOService* BRCMFX::probe(IOService *service, IOService * provider, SInt32 *score) 267 | { 268 | DBGLOG("BRCMFX", "probe is called, service name is %s, provider name is %s", safeString(service->getName()), safeString(provider->getName())); 269 | ADDPR(brcmfx_config).readArguments(provider); 270 | 271 | int index = find_service_index(safeString(service->getName())); 272 | int brcmfx_driver = ADDPR(brcmfx_config).brcmfx_driver; 273 | 274 | bool disable_driver = (brcmfx_driver == -1 && index == AirPort_BrcmNIC_MFG) || (brcmfx_driver != -1 && brcmfx_driver != index); 275 | if (index < 0 || disable_driver) { 276 | DBGLOG("BRCMFX", "probe: disable service %s", safeString(service->getName())); 277 | return nullptr; 278 | } 279 | 280 | PCIHookManager::hookProvider(provider); 281 | if (ADDPR(brcmfx_config).override_aspm && callbackBRCMFX->setASPMState) { 282 | IOReturn result = callbackBRCMFX->setASPMState(provider, provider, ADDPR(brcmfx_config).brcmfx_aspm); 283 | if (result != KERN_SUCCESS) 284 | SYSLOG("BRCMFX", "setASPMState has failed with code 0x%x", result); 285 | } 286 | 287 | IOService *result = FunctionCast(probe, callbackBRCMFX->orgProbe[index])(service, provider, score); 288 | DBGLOG("BRCMFX", "probe is finished with result %s", (result != nullptr) ? "success" : "failed"); 289 | return result; 290 | } 291 | 292 | //============================================================================== 293 | 294 | void BRCMFX::osl_panic(const char *format, ...) 295 | { 296 | if (!strcmp(format, "32KHz LPO Clock not running")) 297 | { 298 | // Ignore LPO panic! 299 | return; 300 | } 301 | 302 | char buf[0x800]; 303 | memset(buf, 0, sizeof(buf)); 304 | 305 | va_list va; 306 | va_start(va, format); 307 | vsnprintf(buf, sizeof(buf), format, va); 308 | va_end(va); 309 | 310 | panic("\"%s\"@/BuildRoot/Library/Caches/com.apple.xbs/Sources/AirPortDriverBrcmNIC/AirPortDriverBrcmNIC-1241.31.1.9/src/shared/macosx_osl.cpp:2029", buf); 311 | } 312 | 313 | //============================================================================== 314 | // 315 | // Find service by name in a specified registry plane (gIO80211FamilyPlane or gIOServicePlane) 316 | // 317 | 318 | IOService* LIBKERN_RETURNS_NOT_RETAINED findService(const IORegistryPlane* plane, const char *service_name) 319 | { 320 | IOService * service = nullptr; 321 | IORegistryIterator * iterator = IORegistryIterator::iterateOver(plane, kIORegistryIterateRecursively); 322 | 323 | if (iterator) 324 | { 325 | size_t len = strlen(service_name); 326 | 327 | IORegistryEntry *res {nullptr}; 328 | while ((res = OSDynamicCast(IORegistryEntry, iterator->getNextObject())) != nullptr) 329 | { 330 | auto resname = safeString(res->getName()); 331 | if (resname && !strncmp(service_name, resname, len)) 332 | { 333 | service = OSDynamicCast(IOService, res); 334 | if (service != nullptr) 335 | break; 336 | } 337 | } 338 | 339 | iterator->release(); 340 | } 341 | 342 | return service; 343 | } 344 | 345 | //============================================================================== 346 | 347 | void BRCMFX::processKernel(KernelPatcher &patcher) 348 | { 349 | DBGLOG("BRCMFX", "processKernel method is called"); 350 | if (!startMatching_symbol && !startMatching_dictionary) 351 | { 352 | startMatching_symbol = reinterpret_cast(patcher.solveSymbol(KernelPatcher::KernelID, "__ZN11IOCatalogue13startMatchingEPK8OSSymbol")); 353 | startMatching_dictionary = reinterpret_cast(patcher.solveSymbol(KernelPatcher::KernelID, "__ZN11IOCatalogue13startMatchingEP12OSDictionary")); 354 | if (!startMatching_symbol && !startMatching_dictionary) 355 | SYSLOG("BRCMFX", "Fail to resolve IOCatalogue::startMatching method, error = %d", patcher.getError()); 356 | } 357 | 358 | if (!removeDrivers) 359 | { 360 | removeDrivers = reinterpret_cast(patcher.solveSymbol(KernelPatcher::KernelID, "__ZN11IOCatalogue13removeDriversEP12OSDictionaryb")); 361 | if (!removeDrivers) 362 | SYSLOG("BRCMFX", "Fail to resolve IOCatalogue::removeDrivers method, error = %d", patcher.getError()); 363 | } 364 | 365 | // Ignore all the errors for other processors 366 | patcher.clearError(); 367 | } 368 | 369 | //============================================================================== 370 | 371 | void BRCMFX::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) 372 | { 373 | static const mach_vm_address_t wlc_set_countrycode_rev[MaxServices] { 374 | reinterpret_cast(BRCMFX::wlc_set_countrycode_rev<0>), 375 | reinterpret_cast(BRCMFX::wlc_set_countrycode_rev<1>), 376 | reinterpret_cast(BRCMFX::wlc_set_countrycode_rev<2>), 377 | reinterpret_cast(wlc_set_countrycode_rev_4331) 378 | }; 379 | 380 | static const mach_vm_address_t siPmuFvcoPllreg[MaxServices] { 381 | reinterpret_cast(BRCMFX::siPmuFvcoPllreg<0>), 382 | reinterpret_cast(BRCMFX::siPmuFvcoPllreg<1>), 383 | reinterpret_cast(BRCMFX::siPmuFvcoPllreg<2>), 384 | reinterpret_cast(BRCMFX::siPmuFvcoPllreg<3>) 385 | }; 386 | 387 | static const mach_vm_address_t checkBoardId[MaxServices] { 388 | reinterpret_cast(BRCMFX::checkBoardId<0>), 389 | reinterpret_cast(BRCMFX::checkBoardId<1>), 390 | reinterpret_cast(BRCMFX::checkBoardId<2>), 391 | reinterpret_cast(BRCMFX::checkBoardId<3>) 392 | }; 393 | 394 | #ifdef DEBUG 395 | static const mach_vm_address_t AirPort_BrcmNIC_setTX_NSS[MaxServices] { 396 | reinterpret_cast(BRCMFX::AirPort_BrcmNIC_setTX_NSS<0>), 397 | reinterpret_cast(BRCMFX::AirPort_BrcmNIC_setTX_NSS<1>), 398 | reinterpret_cast(BRCMFX::AirPort_BrcmNIC_setTX_NSS<2>), 399 | reinterpret_cast(BRCMFX::AirPort_BrcmNIC_setTX_NSS<3>) 400 | }; 401 | 402 | static const mach_vm_address_t AirPort_BrcmNIC_getTX_NSS[MaxServices] { 403 | reinterpret_cast(BRCMFX::AirPort_BrcmNIC_getTX_NSS<0>), 404 | reinterpret_cast(BRCMFX::AirPort_BrcmNIC_getTX_NSS<1>), 405 | reinterpret_cast(BRCMFX::AirPort_BrcmNIC_getTX_NSS<2>), 406 | reinterpret_cast(BRCMFX::AirPort_BrcmNIC_getTX_NSS<3>) 407 | }; 408 | 409 | static const mach_vm_address_t AirPort_BrcmNIC_getNSS[MaxServices] { 410 | reinterpret_cast(BRCMFX::AirPort_BrcmNIC_getNSS<0>), 411 | reinterpret_cast(BRCMFX::AirPort_BrcmNIC_getNSS<1>), 412 | reinterpret_cast(BRCMFX::AirPort_BrcmNIC_getNSS<2>), 413 | reinterpret_cast(BRCMFX::AirPort_BrcmNIC_getNSS<3>) 414 | }; 415 | 416 | static const mach_vm_address_t wlc_ratespec_nss[MaxServices] { 417 | reinterpret_cast(BRCMFX::wlc_ratespec_nss<0>), 418 | reinterpret_cast(BRCMFX::wlc_ratespec_nss<1>), 419 | reinterpret_cast(BRCMFX::wlc_ratespec_nss<2>), 420 | reinterpret_cast(BRCMFX::wlc_ratespec_nss<3>) 421 | }; 422 | #endif 423 | 424 | for (size_t i = 0; i < kextListSize; i++) 425 | { 426 | if (kextList[i].loadIndex == index && !kext_handled[i]) 427 | { 428 | kext_handled[i] = true; 429 | 430 | if (i >= MaxServices) { 431 | setASPMState = reinterpret_cast(patcher.solveSymbol(index, "__ZN11IOPCIDevice12setASPMStateEP9IOServicej")); 432 | if (!setASPMState && getKernelVersion() >= KernelVersion::Yosemite) { 433 | SYSLOG("BRCMFX", "failed to resolve __ZN11IOPCIDevice12setASPMStateEP9IOServicej %d", patcher.getError()); 434 | patcher.clearError(); 435 | } 436 | break; 437 | } 438 | 439 | while (true) 440 | { 441 | DBGLOG("BRCMFX", "found %s", idList[i]); 442 | 443 | // IOServicePlane should keep a pointer to broadcom driver only if it was successfully started 444 | IOService* running_service = findService(gIOServicePlane, serviceNameList[i]); 445 | if (running_service != nullptr) 446 | { 447 | SYSLOG("BRCMFX", "%s driver is already loaded, too late to do patching", serviceNameList[i]); 448 | break; 449 | } 450 | 451 | KernelPatcher::RouteRequest requests[] { 452 | // Failed PCIe configuration (device-id checking) 453 | {symbolList[i][0], start, orgStart[i]}, 454 | // Hook probe method 455 | {symbolList[i][1], probe, orgProbe[i]}, 456 | // Chip identificator checking patch 457 | {symbolList[i][2], siPmuFvcoPllreg[i], orgSiPmuFvcoPllreg[i]}, 458 | // Wi-Fi 5 Ghz/Country code patch (required for 10.11) 459 | {symbolList[i][3], wlc_set_countrycode_rev[i], orgWlcSetCountryCodeRev[i]}, 460 | // Third party device patch 461 | {symbolList[i][4], newVendorString}, 462 | // White list restriction patch 463 | {symbolList[i][5], checkBoardId[i]}, 464 | // Disable "32KHz LPO Clock not running" panic in AirPort_BrcmXXX 465 | {symbolList[i][6], osl_panic}, 466 | #ifdef DEBUG 467 | // Investigate issues with NSS 468 | {symbolList[i][9], AirPort_BrcmNIC_setTX_NSS[i], orgAirPort_BrcmNIC_setTX_NSS[i]}, 469 | {symbolList[i][10], AirPort_BrcmNIC_getTX_NSS[i], orgAirPort_BrcmNIC_getTX_NSS[i]}, 470 | {symbolList[i][11], AirPort_BrcmNIC_getNSS[i], orgAirPort_BrcmNIC_getNSS[i]}, 471 | {symbolList[i][12], wlc_ratespec_nss[i], orgWlcRatespecNss[i]} 472 | #endif 473 | }; 474 | 475 | if (!patcher.routeMultiple(index, requests, address, size)) 476 | SYSLOG("BRCMFX", "at least one basic patch is failed, error = %d", patcher.getError()); 477 | else 478 | DBGLOG("BRCMFX", "all patches are successfuly applied to %s", idList[i]); 479 | 480 | if ((ADDPR(brcmfx_config).brcmfx_driver == -1 && i == AirPort_BrcmNIC_MFG) || 481 | (ADDPR(brcmfx_config).brcmfx_driver != -1 && ADDPR(brcmfx_config).brcmfx_driver != i)) 482 | break; 483 | 484 | if (cpmChanSwitchWhitelist == nullptr && i == AirPort_Brcm4360) 485 | { 486 | cpmChanSwitchWhitelist = reinterpret_cast(patcher.solveSymbol(index, "__cpmChanSwitchWhitelist")); 487 | if (cpmChanSwitchWhitelist != nullptr) 488 | DBGLOG("BRCMFX", "symbol __cpmChanSwitchWhitelist successfuly solved"); 489 | } 490 | 491 | // Disable WOWL (WoWLAN) 492 | if (!ADDPR(brcmfx_config).enable_wowl) 493 | { 494 | patcher.clearError(); 495 | KernelPatcher::RouteRequest requests[] { 496 | {symbolList[i][7], wowCapablePlatform}, 497 | {symbolList[i][8], wlc_wowl_enable} 498 | }; 499 | if (!patcher.routeMultiple(index, requests, address, size)) 500 | SYSLOG("BRCMFX", "wowl disable patch is failed, error = %d", patcher.getError()); 501 | else 502 | DBGLOG("BRCMFX", "wowl disable patch is successfuly applied to %s", idList[i]); 503 | } 504 | break; 505 | } 506 | 507 | ADDPR(brcmfx_config).disabled = true; 508 | 509 | if (!matchingTimer) { 510 | if (!workLoop) 511 | workLoop = IOWorkLoop::workLoop(); 512 | 513 | if (workLoop) { 514 | matchingTimer = IOTimerEventSource::timerEventSource(workLoop, 515 | [](OSObject *owner, IOTimerEventSource *) { 516 | callbackBRCMFX->startMatching(); 517 | }); 518 | 519 | if (matchingTimer) { 520 | IOReturn result = workLoop->addEventSource(matchingTimer); 521 | if (result != kIOReturnSuccess) 522 | SYSLOG("BRCMFX", "addEventSource failed"); 523 | } 524 | else 525 | SYSLOG("BRCMFX", "timerEventSource failed"); 526 | } 527 | else 528 | SYSLOG("BRCMFX", "IOService instance does not have workLoop"); 529 | } 530 | if (matchingTimer) 531 | matchingTimer->setTimeoutMS(1000); 532 | } 533 | } 534 | 535 | // Ignore all the errors for other processors 536 | patcher.clearError(); 537 | } 538 | 539 | //============================================================================== 540 | 541 | void BRCMFX::startMatching() 542 | { 543 | DBGLOG("BRCMFX", "startMatching is called"); 544 | 545 | IOService *service = findService(gIOServicePlane, "FakeBrcm"); 546 | if (service && service->getProvider()) 547 | { 548 | auto bundle = OSDynamicCast(OSString, service->getProperty(kCFBundleIdentifierKey)); 549 | auto ioclass = OSDynamicCast(OSString, service->getProperty(KIOClass)); 550 | bool success = false; 551 | 552 | IOService *provider = service->getProvider(); 553 | if (provider) 554 | { 555 | provider->retain(); 556 | if (service->terminate()) 557 | success = true; 558 | provider->release(); 559 | DBGLOG("BRCMFX", "terminating FakeBrcm with status %d", success); 560 | } 561 | else 562 | success = true; 563 | 564 | if (success && bundle && ioclass && removeDrivers) 565 | { 566 | OSDictionary * dict = OSDictionary::withCapacity(2); 567 | if (dict) { 568 | dict->setObject(kCFBundleIdentifierKey, bundle); 569 | dict->setObject(KIOClass, ioclass); 570 | if (!removeDrivers(gIOCatalogue, dict, false)) 571 | SYSLOG("BRCMFX", "gIOCatalogue->removeDrivers failed"); 572 | else 573 | DBGLOG("BRCMFX", "gIOCatalogue->removeDrivers successful"); 574 | OSSafeReleaseNULL(dict); 575 | } 576 | } 577 | } 578 | 579 | #ifdef DEBUG 580 | for (int i=0; i < MaxServices; i++) 581 | { 582 | int brcmfx_driver = checkBrcmfxDriverValue(i, true); 583 | if (i != brcmfx_driver) 584 | continue; 585 | auto bundle = OSSymbol::withCStringNoCopy(idList[i]); 586 | if (!bundle) 587 | continue; 588 | OSDictionary * dict = OSDictionary::withCapacity(1); 589 | if (dict) { 590 | dict->setObject(kCFBundleIdentifierKey, bundle); 591 | SInt32 generation = 0; 592 | OSOrderedSet *set = gIOCatalogue->findDrivers(dict, &generation); 593 | if (set) { 594 | if (set->getCount() > 0) 595 | DBGLOG("BRCMFX", "gIOCatalogue->findDrivers() returned non-empty ordered set for bundle %s", idList[i]); 596 | else 597 | DBGLOG("BRCMFX", "gIOCatalogue->findDrivers() returned empty ordered set for bundle %s", idList[i]); 598 | } 599 | else { 600 | DBGLOG("BRCMFX", "gIOCatalogue->findDrivers() failed for bundle %s", idList[i]); 601 | } 602 | OSSafeReleaseNULL(dict); 603 | OSSafeReleaseNULL(set); 604 | } 605 | } 606 | #endif 607 | 608 | if (startMatching_symbol) 609 | { 610 | for (int i=0; i < MaxServices; i++) 611 | { 612 | int brcmfx_driver = checkBrcmfxDriverValue(i, true); 613 | if (i != brcmfx_driver) 614 | continue; 615 | const char *bundle_identifier = idList[i]; 616 | 617 | auto bundle = OSSymbol::withCStringNoCopy(bundle_identifier); 618 | if (bundle) { 619 | if (!startMatching_symbol(gIOCatalogue, bundle)) 620 | SYSLOG("BRCMFX", "gIOCatalogue->startMatching(OSSymbol const*) failed for bundle %s", bundle_identifier); 621 | else 622 | DBGLOG("BRCMFX", "gIOCatalogue->startMatching(OSSymbol const*) successful for bundle %s", bundle_identifier); 623 | OSSafeReleaseNULL(bundle); 624 | } 625 | } 626 | } 627 | 628 | if (startMatching_dictionary) 629 | { 630 | OSDictionary* dict = OSDictionary::withCapacity(1); 631 | if (dict) { 632 | const OSSymbol* pci = OSSymbol::withCStringNoCopy("IOPCIDevice"); 633 | if (pci) { 634 | dict->setObject("IOProviderClass", pci); 635 | OSSafeReleaseNULL(pci); 636 | if (!startMatching_dictionary(gIOCatalogue, dict)) 637 | SYSLOG("BRCMFX", "gIOCatalogue->startMatching(OSDictionary *) failed"); 638 | else 639 | DBGLOG("BRCMFX", "gIOCatalogue->startMatching(OSDictionary *) successful"); 640 | } 641 | OSSafeReleaseNULL(dict); 642 | } 643 | } 644 | 645 | IOSleep(200); 646 | if (!atLeastOneServiceStarted && --matchingLeftAttemptCounter >= 0 && matchingTimer) 647 | { 648 | DBGLOG("BRCMFX", "startMatching did not detect any started services, schedule one more attempt"); 649 | matchingTimer->setTimeoutMS(1000); 650 | } 651 | } 652 | -------------------------------------------------------------------------------- /AirportBrcmFixup/kern_brcmfx.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // kern_brcmfx.hpp 3 | // AirportBrcmFixup 4 | // 5 | // Copyright © 2017 lvs1974. All rights reserved. 6 | // 7 | 8 | #ifndef kern_brcmfx_hpp 9 | #define kern_brcmfx_hpp 10 | 11 | #include "kern_misc.hpp" 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | 20 | class BRCMFX { 21 | public: 22 | bool init(); 23 | void deinit(); 24 | 25 | private: 26 | /** 27 | * Patch kernel 28 | * 29 | * @param patcher KernelPatcher instance 30 | */ 31 | void processKernel(KernelPatcher &patcher); 32 | 33 | /** 34 | * Patch kext if needed and prepare other patches 35 | * 36 | * @param patcher KernelPatcher instance 37 | * @param index kinfo handle 38 | * @param address kinfo load address 39 | * @param size kinfo memory size 40 | */ 41 | void processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size); 42 | 43 | /** 44 | * Execute postponed matching 45 | */ 46 | void startMatching(); 47 | 48 | 49 | /** 50 | * Symbol types 51 | */ 52 | using IOCatalogue_startMatching_symbol = bool (*)(void *that, OSSymbol const* bundle_identifier); 53 | using IOCatalogue_startMatching_dictionary = bool (*)(void *that, OSDictionary *matching); 54 | using IOCatalogue_removeDrivers = bool (*)(void *that, OSDictionary *matching, bool doNubMatching); 55 | using IOPCIDevice_setASPMState = IOReturn (*)(void *pciDevice, IOService *service, IOOptionBits state); 56 | 57 | /** 58 | * Hooked methods / callbacks 59 | */ 60 | static bool start(IOService *service, IOService* provider); 61 | static IOService* probe(IOService *service, IOService * provider, SInt32 *score); 62 | static void osl_panic(const char *format, ...); 63 | static const OSSymbol* newVendorString(void); 64 | 65 | template 66 | static bool checkBoardId(void *that, const char *boardID); 67 | static bool wlc_wowl_enable(int64_t **a1); 68 | static bool wowCapablePlatform(void *that); 69 | 70 | template 71 | static int64_t wlc_set_countrycode_rev(int64_t a1, const char *country_code, int a3); 72 | static int64_t wlc_set_countrycode_rev_4331(int64_t a1, int64_t a2, const char *country_code, int a4); 73 | 74 | template 75 | static int64_t siPmuFvcoPllreg(uint32_t *a1, int64_t a2, int64_t a3); 76 | 77 | #ifdef DEBUG 78 | template 79 | static IOReturn AirPort_BrcmNIC_setTX_NSS(void *that, OSObject*, apple80211_tx_nss_data*); 80 | template 81 | static IOReturn AirPort_BrcmNIC_getTX_NSS(void *that, OSObject*, apple80211_tx_nss_data*); 82 | template 83 | static IOReturn AirPort_BrcmNIC_getNSS(void *that, OSObject*, apple80211_nss_data*); 84 | template 85 | static int64_t wlc_ratespec_nss(int a1); 86 | #endif 87 | 88 | /** 89 | * Trampolines for original method invocations 90 | */ 91 | mach_vm_address_t orgStart[MaxServices] {}; 92 | mach_vm_address_t orgProbe[MaxServices] {}; 93 | mach_vm_address_t orgWlcSetCountryCodeRev[MaxServices] {}; 94 | mach_vm_address_t orgSiPmuFvcoPllreg[MaxServices] {}; 95 | 96 | #ifdef DEBUG 97 | mach_vm_address_t orgAirPort_BrcmNIC_setTX_NSS[MaxServices] {}; 98 | mach_vm_address_t orgAirPort_BrcmNIC_getTX_NSS[MaxServices] {}; 99 | mach_vm_address_t orgAirPort_BrcmNIC_getNSS[MaxServices] {}; 100 | mach_vm_address_t orgWlcRatespecNss[MaxServices] {}; 101 | #endif 102 | 103 | // access to IOCatalogue methods 104 | IOCatalogue_startMatching_symbol startMatching_symbol {}; 105 | IOCatalogue_startMatching_dictionary startMatching_dictionary {}; 106 | IOCatalogue_removeDrivers removeDrivers {}; 107 | IOPCIDevice_setASPMState setASPMState {}; 108 | 109 | const char** cpmChanSwitchWhitelist {}; 110 | _Atomic(bool) atLeastOneServiceStarted = false; 111 | IOWorkLoop *workLoop {}; 112 | int matchingLeftAttemptCounter {9}; 113 | IOTimerEventSource *matchingTimer {}; 114 | }; 115 | 116 | #endif /* kern_brcmfx_hpp */ 117 | -------------------------------------------------------------------------------- /AirportBrcmFixup/kern_config.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // kern_config.hpp 3 | // AirportBrcmFixup 4 | // 5 | // Copyright © 2016-2017 lvs1974. All rights reserved. 6 | // 7 | 8 | #ifndef kern_config_private_h 9 | #define kern_config_private_h 10 | 11 | #include 12 | #include 13 | 14 | 15 | class Configuration { 16 | public: 17 | /** 18 | * Possible boot arguments 19 | */ 20 | static constexpr const char *bootargOff {"-brcmfxoff"}; 21 | static constexpr const char *bootargDebug {"-brcmfxdbg"}; 22 | static constexpr const char *bootargBeta {"-brcmfxbeta"}; 23 | static constexpr const char *bootargBrcmEnableWowl {"-brcmfx-wowl"}; // enable WOWL 24 | static constexpr const char *bootargBrcmAllDrv {"-brcmfx-alldrv"}; // skip driver availability check (which drivers available in the current system) 25 | static constexpr const char *bootargBrcmCountry {"brcmfx-country"}; // 5 Ghz patch - change default country 26 | static constexpr const char *bootargBrcmDriver {"brcmfx-driver"}; 27 | static constexpr const char *bootargBrcmAspm {"brcmfx-aspm"}; 28 | static constexpr const char *bootargDelay {"brcmfx-delay"}; 29 | 30 | /** 31 | * Retrieve boot arguments 32 | * 33 | * @return true if allowed to continue 34 | */ 35 | void readArguments(IOService* provider = nullptr); 36 | bool awaitPublishing(IORegistryEntry *obj); 37 | 38 | char country_code[5] {"US"}; 39 | 40 | bool disabled {false}; 41 | bool enable_wowl {false}; 42 | 43 | int32_t brcmfx_driver {-1}; 44 | 45 | IOOptionBits brcmfx_aspm {0}; 46 | bool override_aspm {false}; 47 | 48 | bool enable_all_drv {false}; 49 | 50 | bool config_is_ready {false}; 51 | 52 | uint32_t start_delay {0}; 53 | 54 | Configuration() = default; 55 | }; 56 | 57 | extern Configuration ADDPR(brcmfx_config); 58 | 59 | #endif /* kern_config_private_h */ 60 | -------------------------------------------------------------------------------- /AirportBrcmFixup/kern_fakebrcm.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // kern_fakebrcm.cpp 3 | // AirportBrcmFixup 4 | // 5 | // Copyright © 2017 lvs1974. All rights reserved. 6 | // 7 | 8 | #include 9 | 10 | #include "kern_config.hpp" 11 | #include "kern_fakebrcm.hpp" 12 | #include 13 | 14 | #include "kern_misc.hpp" 15 | 16 | 17 | OSDefineMetaClassAndStructors(FakeBrcm, IOService); 18 | 19 | 20 | IOService *PCIHookManager::service_provider{nullptr}; 21 | WIOKit::t_PCIConfigRead16 PCIHookManager::orgConfigRead16 {nullptr}; 22 | WIOKit::t_PCIConfigRead32 PCIHookManager::orgConfigRead32 {nullptr}; 23 | 24 | bool FakeBrcm::service_found {false}; 25 | 26 | //============================================================================== 27 | 28 | bool PCIHookManager::isServiceSupported(IORegistryEntry* service) 29 | { 30 | if (service == service_provider) 31 | return true; 32 | 33 | for (int i=0; igetName())) == 0) 36 | return true; 37 | } 38 | return false; 39 | } 40 | 41 | //============================================================================== 42 | 43 | UInt16 PCIHookManager::configRead16(IORegistryEntry *service, UInt32 space, UInt8 offset) 44 | { 45 | UInt16 result = orgConfigRead16(service, space, offset); 46 | UInt16 newResult = result; 47 | 48 | if ((offset == WIOKit::PCIRegister::kIOPCIConfigVendorID || offset == WIOKit::PCIRegister::kIOPCIConfigDeviceID) && isServiceSupported(service)) 49 | switch (offset) 50 | { 51 | case WIOKit::PCIRegister::kIOPCIConfigVendorID: 52 | { 53 | UInt32 vendor; 54 | if (WIOKit::getOSDataValue(service, "vendor-id", vendor)) 55 | newResult = vendor; 56 | break; 57 | } 58 | case WIOKit::PCIRegister::kIOPCIConfigDeviceID: 59 | { 60 | UInt32 device; 61 | if (WIOKit::getOSDataValue(service, "device-id", device)) 62 | newResult = device; 63 | break; 64 | } 65 | } 66 | 67 | if (newResult != result) 68 | DBGLOG("BRCMFX", "PCIHookManager::configRead16: name = %s, source value = 0x%04x replaced with value = 0x%04x", safeString(service->getName()), result, newResult); 69 | 70 | return newResult; 71 | } 72 | 73 | //============================================================================== 74 | 75 | UInt32 PCIHookManager::configRead32(IORegistryEntry *service, UInt32 space, UInt8 offset) 76 | { 77 | UInt32 result = orgConfigRead32(service, space, offset); 78 | UInt32 newResult = result; 79 | 80 | // OS X does a non-aligned read, which still returns full vendor / device ID 81 | if ((offset == WIOKit::PCIRegister::kIOPCIConfigVendorID || offset == WIOKit::PCIRegister::kIOPCIConfigDeviceID) && isServiceSupported(service)) 82 | { 83 | UInt32 vendor, device; 84 | if (WIOKit::getOSDataValue(service, "vendor-id", vendor)) 85 | newResult = (newResult & 0xFFFF0000) | vendor; 86 | if (WIOKit::getOSDataValue(service, "device-id", device)) 87 | newResult = (device << 16) | (newResult & 0xFFFF); 88 | } 89 | 90 | if (newResult != result) 91 | DBGLOG("BRCMFX", "PCIHookManager::configRead32: name = %s, source value = 0x%08x replaced with value = 0x%08x", safeString(service->getName()), result, newResult); 92 | 93 | return newResult; 94 | } 95 | 96 | //============================================================================== 97 | 98 | void PCIHookManager::hookProvider(IOService *provider) 99 | { 100 | if (service_provider == nullptr) 101 | { 102 | ADDPR(brcmfx_config).readArguments(provider); 103 | } 104 | service_provider = provider; 105 | 106 | UInt32 vendor, device; 107 | if (WIOKit::getOSDataValue(provider, "device-id", device) && WIOKit::getOSDataValue(provider, "vendor-id", vendor)) 108 | { 109 | if (WIOKit::readPCIConfigValue(provider, WIOKit::PCIRegister::kIOPCIConfigDeviceID) == device && 110 | WIOKit::readPCIConfigValue(provider, WIOKit::PCIRegister::kIOPCIConfigVendorID) == vendor) 111 | { 112 | DBGLOG("BRCMFX", "PCIHookManager::hookProvider: hook is not required since vendor-id && device-id are the same"); 113 | return; 114 | } 115 | } 116 | 117 | if (orgConfigRead16 == nullptr) 118 | if (KernelPatcher::routeVirtual(provider, WIOKit::PCIConfigOffset::ConfigRead16, configRead16, &orgConfigRead16)) 119 | DBGLOG("BRCMFX", "PCIHookManager::hookProvider for configRead16 was successful"); 120 | 121 | if (orgConfigRead32 == nullptr) 122 | if (KernelPatcher::routeVirtual(provider, WIOKit::PCIConfigOffset::ConfigRead32, configRead32, &orgConfigRead32)) 123 | DBGLOG("BRCMFX", "PCIHookManager::hookProvider for configRead32 was successful"); 124 | } 125 | 126 | //============================================================================== 127 | 128 | bool FakeBrcm::init(OSDictionary *propTable) 129 | { 130 | if (ADDPR(brcmfx_config).disabled) 131 | { 132 | DBGLOG("BRCMFX", "FakeBrcm::init(): FakeBrcm disabled"); 133 | return false; 134 | } 135 | 136 | DBGLOG("BRCMFX", "FakeBrcm::init()"); 137 | 138 | bool ret = super::init(propTable); 139 | if (!ret) 140 | { 141 | SYSLOG("BRCMFX", "FakeBrcm super::init returned false\n"); 142 | return false; 143 | } 144 | 145 | return true; 146 | } 147 | 148 | //============================================================================== 149 | 150 | bool FakeBrcm::attach(IOService *provider) 151 | { 152 | PCIHookManager::hookProvider(provider); 153 | 154 | return super::attach(provider); 155 | } 156 | 157 | //============================================================================== 158 | 159 | IOService* FakeBrcm::probe(IOService * provider, SInt32 *score) 160 | { 161 | DBGLOG("BRCMFX", "FakeBrcm::probe(), version %s", xStringify(MODULE_VERSION)); 162 | 163 | if (!ADDPR(startSuccess)) 164 | { 165 | return nullptr; 166 | } 167 | 168 | IOService* ret = super::probe(provider, score); 169 | if (!ret) 170 | { 171 | SYSLOG("BRCMFX", "FakeBrcm super::probe returned nullptr\n"); 172 | return nullptr; 173 | } 174 | 175 | if (ADDPR(brcmfx_config).disabled) 176 | { 177 | DBGLOG("BRCMFX", "FakeBrcm::probe(): FakeBrcm disabled"); 178 | return ret; 179 | } 180 | 181 | DBGLOG("BRCMFX", "FakeBrcm::probe(): service provider is %s", safeString(provider->getName())); 182 | 183 | ADDPR(brcmfx_config).readArguments(provider); 184 | 185 | for (int i = 0; i < MaxServices; i++) 186 | { 187 | int brcmfx_driver = checkBrcmfxDriverValue(i, true); 188 | if (i != brcmfx_driver) 189 | continue; 190 | 191 | auto bundle = OSSymbol::withCStringNoCopy(idList[i]); 192 | if (bundle) { 193 | OSDictionary * dict = OSDictionary::withCapacity(1); 194 | if (dict) { 195 | dict->setObject(kCFBundleIdentifierKey, bundle); 196 | SInt32 generation = 0; 197 | OSOrderedSet *set = gIOCatalogue->findDrivers(dict, &generation); 198 | if (set) { 199 | if (set->getCount() > 0) 200 | { 201 | DBGLOG("BRCMFX", "FakeBrcm::probe(): gIOCatalogue->findDrivers() returned non-empty ordered set for bundle %s", idList[i]); 202 | service_found = true; 203 | 204 | } 205 | else 206 | DBGLOG("BRCMFX", "FakeBrcm::probe(): gIOCatalogue->findDrivers() returned empty ordered set for bundle %s", idList[i]); 207 | } 208 | else { 209 | SYSLOG("BRCMFX", "FakeBrcm::probe(): gIOCatalogue->findDrivers() failed for bundle %s", idList[i]); 210 | } 211 | OSSafeReleaseNULL(dict); 212 | OSSafeReleaseNULL(set); 213 | } 214 | } 215 | } 216 | 217 | if (service_found) 218 | { 219 | SInt32 new_probe_score = 6000; 220 | DBGLOG("BRCMFX", "FakeBrcm::probe() will change score from %d to %d", *score, new_probe_score); 221 | *score = new_probe_score; // change probe score to be the first in the list 222 | } 223 | else 224 | { 225 | *score = -2000; 226 | DBGLOG("BRCMFX", "FakeBrcm::probe(): fallback to original driver"); 227 | } 228 | 229 | return ret; 230 | } 231 | 232 | //============================================================================== 233 | 234 | bool FakeBrcm::start(IOService *provider) 235 | { 236 | DBGLOG("BRCMFX", "FakeBrcm::start()"); 237 | 238 | if (!ADDPR(startSuccess)) 239 | { 240 | return false; 241 | } 242 | 243 | if (ADDPR(brcmfx_config).disabled) 244 | { 245 | DBGLOG("BRCMFX", "FakeBrcm::start(): FakeBrcm disabled"); 246 | return false; 247 | } 248 | 249 | if (!super::start(provider)) 250 | { 251 | SYSLOG("BRCMFX", "FakeBrcm super::start returned false\n"); 252 | return false; 253 | } 254 | 255 | if (!service_found) 256 | { 257 | SYSLOG("BRCMFX", "FakeBrcm::start(): fallback to original driver"); 258 | return false; 259 | } 260 | 261 | PCIHookManager::hookProvider(provider); 262 | 263 | return true; 264 | } 265 | 266 | //============================================================================== 267 | 268 | void FakeBrcm::stop(IOService *provider) 269 | { 270 | DBGLOG("BRCMFX", "FakeBrcm::stop()"); 271 | super::stop(provider); 272 | } 273 | 274 | //============================================================================== 275 | 276 | void FakeBrcm::free() 277 | { 278 | DBGLOG("BRCMFX", "FakeBrcm::free()"); 279 | super::free(); 280 | } 281 | -------------------------------------------------------------------------------- /AirportBrcmFixup/kern_fakebrcm.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // kern_fakebrcm.hpp 3 | // AirportBrcmFixup 4 | // 5 | // Copyright © 2017 lvs1974. All rights reserved. 6 | // 7 | 8 | #ifndef FakeBrcm_h 9 | #define FakeBrcm_h 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | class EXPORT PCIHookManager 17 | { 18 | static bool isServiceSupported(IORegistryEntry* service); 19 | static UInt16 configRead16(IORegistryEntry *service, UInt32 bits, UInt8 offset); 20 | static UInt32 configRead32(IORegistryEntry *service, UInt32 bits, UInt8 offset); 21 | 22 | static IOService *service_provider; 23 | static WIOKit::t_PCIConfigRead16 orgConfigRead16; 24 | static WIOKit::t_PCIConfigRead32 orgConfigRead32; 25 | 26 | public: 27 | static void hookProvider(IOService* provider); 28 | }; 29 | 30 | class EXPORT FakeBrcm : public IOService 31 | { 32 | OSDeclareDefaultStructors(FakeBrcm); 33 | typedef IOService super; 34 | 35 | static bool service_found; 36 | 37 | public: 38 | virtual bool init(OSDictionary *propTable) override; 39 | virtual bool attach(IOService *provider) override; 40 | virtual IOService* probe(IOService * provider, SInt32 *score) override; 41 | virtual bool start(IOService *provider) override; 42 | virtual void stop(IOService *provider) override; 43 | virtual void free() override; 44 | }; 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /AirportBrcmFixup/kern_misc.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // kern_misc.hpp 3 | // AirportBrcmFixup 4 | // 5 | // Copyright © 2017 lvs1974. All rights reserved. 6 | // 7 | 8 | #ifndef kern_misc_hpp 9 | #define kern_misc_hpp 10 | 11 | #include 12 | #include "kern_config.hpp" 13 | 14 | #define kCFBundleIdentifierKey "CFBundleIdentifier" 15 | #define kCFBundleIdentifierKernelKey "CFBundleIdentifierKernel" 16 | #define KIOClass "IOClass" 17 | 18 | enum AirportServices { 19 | AirPort_BrcmNIC_MFG = 0, 20 | AirPort_Brcm4360, 21 | AirPort_BrcmNIC, 22 | AirPort_Brcm4331, 23 | MaxServices 24 | }; 25 | 26 | static const char *serviceNameList[MaxServices] { 27 | "AirPort_BrcmNIC_MFG", 28 | "AirPort_Brcm4360", 29 | "AirPort_BrcmNIC", 30 | "AirPort_Brcm4331" 31 | }; 32 | 33 | static const char *idList[MaxServices] { 34 | "com.apple.driver.AirPort.BrcmNIC-MFG", 35 | "com.apple.driver.AirPort.Brcm4360", 36 | "com.apple.driver.AirPort.BrcmNIC", 37 | "com.apple.driver.AirPort.Brcm4331" 38 | "com.apple.driver.AirPort.Brcm4331" 39 | }; 40 | 41 | static const char *binList[MaxServices][2] { 42 | {"/System/Library/Extensions/AirPortBrcmNIC-MFG.kext/Contents/MacOS/AirPortBrcmNIC-MFG", ""}, 43 | {"/System/Library/Extensions/IO80211Family.kext/Contents/PlugIns/AirPortBrcm4360.kext/Contents/MacOS/AirPortBrcm4360", ""}, 44 | {"/System/Library/Extensions/IO80211Family.kext/Contents/PlugIns/AirPortBrcmNIC.kext/Contents/MacOS/AirPortBrcmNIC", "/System/Library/Extensions/IO80211FamilyLegacy.kext/Contents/PlugIns/AirPortBrcmNIC.kext/Contents/MacOS/AirPortBrcmNIC"}, 45 | {"/System/Library/Extensions/IO80211Family.kext/Contents/PlugIns/AirPortBrcm4331.kext/Contents/MacOS/AirPortBrcm4331", ""} 46 | }; 47 | 48 | static const char *symbolList[MaxServices][13] { 49 | {"__ZN19AirPort_BrcmNIC_MFG5startEP9IOService", "__ZN19AirPort_BrcmNIC_MFG5probeEP9IOServicePi", "_si_pmu_fvco_pllreg", "_wlc_set_countrycode_rev", 50 | "__ZNK19AirPort_BrcmNIC_MFG15newVendorStringEv", "__ZN19AirPort_BrcmNIC_MFG12checkBoardIdEPKc", nullptr, 51 | "__ZN19AirPort_BrcmNIC_MFG18wowCapablePlatformEv", "_wlc_wowl_enable", nullptr, nullptr, nullptr, nullptr }, 52 | 53 | {"__ZN16AirPort_Brcm43605startEP9IOService", "__ZN16AirPort_Brcm43605probeEP9IOServicePi" , "_si_pmu_fvco_pllreg", "_wlc_set_countrycode_rev", 54 | "__ZNK16AirPort_Brcm436015newVendorStringEv", "__ZN16AirPort_Brcm436012checkBoardIdEPKc", nullptr, 55 | "__ZN16AirPort_Brcm436018wowCapablePlatformEv", "_wlc_wowl_enable", nullptr, nullptr, nullptr, nullptr }, 56 | 57 | {"__ZN15AirPort_BrcmNIC5startEP9IOService", "__ZN15AirPort_BrcmNIC5probeEP9IOServicePi", "_si_pmu_fvco_pllreg", "_wlc_set_countrycode_rev", 58 | "__ZNK15AirPort_BrcmNIC15newVendorStringEv", "__ZN15AirPort_BrcmNIC12checkBoardIdEPKc", "_osl_panic", 59 | "__ZN15AirPort_BrcmNIC18wowCapablePlatformEv", "_wlc_wowl_enable" , "__ZN15AirPort_BrcmNIC9setTX_NSSEP8OSObjectP22apple80211_tx_nss_data", 60 | "__ZN15AirPort_BrcmNIC9getTX_NSSEP8OSObjectP22apple80211_tx_nss_data", "__ZN15AirPort_BrcmNIC6getNSSEP8OSObjectP19apple80211_nss_data", "_wlc_ratespec_nss" }, 61 | 62 | {"__ZN16AirPort_Brcm43315startEP9IOService", "__ZN16AirPort_Brcm43315probeEP9IOServicePi", nullptr, "_wlc_set_countrycode_rev", 63 | "__ZNK16AirPort_Brcm433115newVendorStringEv", nullptr, nullptr, 64 | "__ZN16AirPort_Brcm433118wowCapablePlatformEv", "_wlc_wowl_enable", nullptr, nullptr, nullptr, nullptr } 65 | }; 66 | 67 | /** 68 | * find service internal index by name 69 | */ 70 | 71 | inline int find_service_index(const char* service_name) 72 | { 73 | for (int i=0; i= KernelVersion::Catalina) 97 | { 98 | if (brcmfx_driver == AirPort_BrcmNIC_MFG || brcmfx_driver == AirPort_Brcm4331) { 99 | if (!skip_log) { 100 | DBGLOG("BRCMFX", "brcmfx-driver %d is not supported in osx Catalina and over", brcmfx_driver); 101 | } 102 | return -1; 103 | } 104 | if (getKernelVersion() >= KernelVersion::BigSur) 105 | { 106 | if (brcmfx_driver == AirPort_Brcm4360) { 107 | if (!skip_log) { 108 | DBGLOG("BRCMFX", "brcmfx-driver %d is not supported in osx Big Sur and over", brcmfx_driver); 109 | } 110 | return -1; 111 | } 112 | } 113 | } 114 | } 115 | 116 | return brcmfx_driver; 117 | } 118 | 119 | struct PACKED apple80211_tx_nss_data 120 | { 121 | uint32_t version; 122 | uint8_t nss; 123 | }; 124 | 125 | struct PACKED apple80211_nss_data 126 | { 127 | uint32_t version; 128 | uint8_t nss; 129 | }; 130 | 131 | #endif /* kern_misc_hpp */ 132 | -------------------------------------------------------------------------------- /AirportBrcmFixup/kern_start.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // kern_start.cpp 3 | // AirportBrcmFixup 4 | // 5 | // Copyright © 2017 lvs1974. All rights reserved. 6 | // 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "kern_config.hpp" 14 | #include "kern_brcmfx.hpp" 15 | 16 | static BRCMFX brcmfx; 17 | 18 | Configuration ADDPR(brcmfx_config); 19 | 20 | const char *bootargOff[] { 21 | ADDPR(brcmfx_config).bootargOff 22 | }; 23 | 24 | const char *bootargDebug[] { 25 | ADDPR(brcmfx_config).bootargDebug 26 | }; 27 | 28 | const char *bootargBeta[] { 29 | ADDPR(brcmfx_config).bootargBeta 30 | }; 31 | 32 | 33 | bool Configuration::awaitPublishing(IORegistryEntry *obj) 34 | { 35 | size_t counter = 0; 36 | while (counter < 256) { 37 | if (obj->inPlane(gIOServicePlane)) { 38 | DBGLOG("BRCMFX", "pci device %s is in service plane %lu", safeString(obj->getName()), counter); 39 | return true; 40 | } 41 | DBGLOG("BRCMFX", "pci device %s is not in service plane %lu, polling", safeString(obj->getName()), counter); 42 | 43 | if (obj->getProperty("IOPCIConfigured")) { 44 | DBGLOG("dev", "pci bridge %s is configured %lu", safeString(obj->getName()), counter); 45 | break; 46 | } 47 | DBGLOG("BRCMFX", "pci bridge %s is not configured %lu, polling", safeString(obj->getName()), counter); 48 | ++counter; 49 | IOSleep(20); 50 | } 51 | 52 | SYSLOG("BRCMFX", "found dead pci device %s", safeString(obj->getName())); 53 | return false; 54 | } 55 | 56 | void Configuration::readArguments(IOService* provider) 57 | { 58 | if (!provider) 59 | { 60 | disabled = checkKernelArgument(bootargOff); 61 | 62 | PE_parse_boot_argn(bootargBrcmCountry, country_code, sizeof(country_code)); 63 | 64 | PE_parse_boot_argn(bootargBrcmDriver, &brcmfx_driver, sizeof(brcmfx_driver)); 65 | brcmfx_driver = checkBrcmfxDriverValue(brcmfx_driver); 66 | 67 | enable_wowl = checkKernelArgument("-brcmfxwowl") || checkKernelArgument(bootargBrcmEnableWowl); 68 | enable_all_drv = checkKernelArgument(bootargBrcmAllDrv); 69 | 70 | if (PE_parse_boot_argn(bootargBrcmAspm, &brcmfx_aspm, sizeof(brcmfx_aspm))) 71 | override_aspm = true; 72 | PE_parse_boot_argn(bootargDelay, &start_delay, sizeof(start_delay)); 73 | } 74 | else if (!config_is_ready) 75 | { 76 | awaitPublishing(provider); 77 | 78 | auto pciDevice = OSDynamicCast(IOPCIDevice, provider); 79 | if (!pciDevice) { 80 | DBGLOG("BRCMFX", "Provider is not IOPCIDevice"); 81 | return; 82 | } 83 | 84 | if (PE_parse_boot_argn(bootargBrcmAspm, &brcmfx_aspm, sizeof(brcmfx_aspm))) { 85 | DBGLOG("BRCMFX", "%s in boot-arg is set to %d", bootargBrcmAspm, brcmfx_aspm); 86 | override_aspm = true; 87 | } else if (WIOKit::getOSDataValue(provider, bootargBrcmAspm, brcmfx_aspm)) { 88 | DBGLOG("BRCMFX", "%s in ioreg is set to %d", bootargBrcmAspm, brcmfx_aspm); 89 | override_aspm = true; 90 | } 91 | 92 | if (PE_parse_boot_argn(bootargDelay, &start_delay, sizeof(start_delay))) { 93 | DBGLOG("BRCMFX", "%s in boot-arg is set to %d", bootargDelay, start_delay); 94 | } else if (WIOKit::getOSDataValue(provider, bootargDelay, start_delay)) { 95 | DBGLOG("BRCMFX", "%s in ioreg is set to %d", bootargDelay, start_delay); 96 | } 97 | 98 | if (brcmfx_aspm != 0xFF) 99 | { 100 | uint16_t vendorID = pciDevice->configRead16(WIOKit::PCIRegister::kIOPCIConfigVendorID); 101 | uint16_t deviceID = pciDevice->configRead16(WIOKit::PCIRegister::kIOPCIConfigDeviceID); 102 | uint16_t subSystemVendorID = pciDevice->configRead16(WIOKit::PCIRegister::kIOPCIConfigSubSystemVendorID); 103 | bool bcm4350 = (vendorID == 0x14e4 && deviceID == 0x43a3 && subSystemVendorID != 0x106b); 104 | // change APSM flags if value has been forced or for Broadcom BCM4350 chipset 105 | if (override_aspm || bcm4350 || (getKernelVersion() >= KernelVersion::Monterey)) 106 | { 107 | override_aspm = true; 108 | DBGLOG("BRCMFX", "Configuration::readArguments: override aspm, subsystem-vendor-id = 0x%04x, subsystem-id = 0x%04x", 109 | subSystemVendorID, pciDevice->configRead16(WIOKit::PCIRegister::kIOPCIConfigSubSystemID)); 110 | auto pci_aspm_default = OSDynamicCast(OSNumber, provider->getProperty("pci-aspm-default")); 111 | if (pci_aspm_default == nullptr || pci_aspm_default->unsigned32BitValue() != brcmfx_aspm) 112 | { 113 | DBGLOG("BRCMFX", "Configuration::readArguments: pci-aspm-default needs to be set to %d", brcmfx_aspm); 114 | provider->setProperty("pci-aspm-default", brcmfx_aspm, 32); 115 | } 116 | } 117 | } 118 | else 119 | override_aspm = false; 120 | 121 | UInt32 value = 0; 122 | if ((enable_wowl = checkKernelArgument(bootargBrcmEnableWowl))) { 123 | DBGLOG("BRCMFX", "%s in boot-arg is set to %d", bootargBrcmEnableWowl, enable_wowl); 124 | } 125 | else if (WIOKit::getOSDataValue(provider, &bootargBrcmEnableWowl[1], enable_wowl)) { 126 | DBGLOG("BRCMFX", "%s in ioreg is set to %d", &bootargBrcmEnableWowl[1], enable_wowl); 127 | } 128 | else if (WIOKit::getOSDataValue(provider, &bootargBrcmEnableWowl[1], value)) { 129 | DBGLOG("BRCMFX", "%s in ioreg is set to %d", &bootargBrcmEnableWowl[1], value); 130 | enable_wowl = (value != 0); 131 | } 132 | 133 | if ((enable_all_drv = checkKernelArgument(bootargBrcmAllDrv))) { 134 | DBGLOG("BRCMFX", "%s in boot-arg is set to %d", bootargBrcmAllDrv, enable_all_drv); 135 | } 136 | else if (WIOKit::getOSDataValue(provider, &bootargBrcmAllDrv[1], enable_all_drv)) { 137 | DBGLOG("BRCMFX", "%s in ioreg is set to %d", &bootargBrcmAllDrv[1], enable_all_drv); 138 | } 139 | else if (WIOKit::getOSDataValue(provider, &bootargBrcmAllDrv[1], value)) { 140 | DBGLOG("BRCMFX", "%s in ioreg is set to %d", &bootargBrcmAllDrv[1], value); 141 | enable_all_drv = (value != 0); 142 | } 143 | 144 | if (PE_parse_boot_argn(bootargBrcmDriver, &brcmfx_driver, sizeof(brcmfx_driver))) { 145 | DBGLOG("BRCMFX", "%s in boot-arg is set to %d", bootargBrcmDriver, brcmfx_driver); 146 | } else if (WIOKit::getOSDataValue(provider, bootargBrcmDriver, brcmfx_driver)) { 147 | DBGLOG("BRCMFX", "%s in ioreg is set to %d", bootargBrcmDriver, brcmfx_driver); 148 | } 149 | brcmfx_driver = checkBrcmfxDriverValue(brcmfx_driver); 150 | 151 | if (PE_parse_boot_argn(bootargBrcmCountry, country_code, sizeof(country_code))) { 152 | DBGLOG("BRCMFX", "%s in boot-arg is set to %d", bootargBrcmCountry, country_code); 153 | } else { 154 | auto data = OSDynamicCast(OSData, provider->getProperty(bootargBrcmCountry)); 155 | if (data) { 156 | lilu_os_strncpy(country_code, reinterpret_cast(data->getBytesNoCopy()), data->getLength()); 157 | DBGLOG("BRCMFX", "%s in ioreg is set to %s", bootargBrcmCountry, country_code); 158 | } 159 | } 160 | 161 | config_is_ready = true; 162 | } 163 | } 164 | 165 | PluginConfiguration ADDPR(config) { 166 | xStringify(PRODUCT_NAME), 167 | parseModuleVersion(xStringify(MODULE_VERSION)), 168 | LiluAPI::AllowNormal | LiluAPI::AllowInstallerRecovery | LiluAPI::AllowSafeMode, 169 | bootargOff, arrsize(bootargOff), 170 | bootargDebug, arrsize(bootargDebug), 171 | bootargBeta, arrsize(bootargBeta), 172 | KernelVersion::MountainLion, 173 | KernelVersion::Sequoia, 174 | []() { 175 | ADDPR(brcmfx_config).readArguments(); 176 | brcmfx.init(); 177 | } 178 | }; 179 | -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | AirportBrcmFixup Changelog 2 | ============================ 3 | #### v2.1.9 4 | - Added constants for macOS 15 support 5 | 6 | #### v2.1.8 7 | - Added constants for macOS 14 support for use with OCLP 8 | 9 | #### v2.1.7 10 | - Override methods AirPort_BrcmNIC::setTX_NSS, AirPort_BrcmNIC::getTX_NSS and AirPort_BrcmNIC::getNSS to investigate NSS issues. 11 | Original method is called, and debug version of kext (with boot-arg -brcmfxdbg) prints info into log 12 | 13 | #### v2.1.6 14 | - Added constants for macOS 13 support 15 | 16 | #### v2.1.5 17 | - Fix compilation issues in Xcode 13.3.1 18 | - Fix patching of AirPortBrcmNIC for Monterey (kext located in IO80211FamilyLegacy.kext/PlugIns) 19 | 20 | #### v2.1.4 21 | - boot-arg and property `brcmfx-delay` (Number) delays start of native broadcom driver for specified amount of milliseconds. Can be required for successful start in macOS Monterey 12.1 and newer versions. 22 | 23 | #### v2.1.3 24 | - Added constants for macOS 12 support 25 | 26 | #### v2.1.2 27 | - Do not patch airport drivers missing in the system (set of available drivers depends on the system version). 28 | For systems with manually added airport drivers this behaviour can be overridden by boot-arg or property `brcmfx-alldrv` 29 | 30 | #### v2.1.1 31 | - Fix an issue with posponed matching (method IOTimerEventSource::timerEventSource could fail) 32 | 33 | #### v2.1.0 34 | - Add pci14e4,4331, pci14e4,4353 and pci14e4,4357 into AirPortBrcmNIC_Injector.kext (in 11.0 only AirPortBrcmNIC can support these devices) 35 | - Added MacKernelSDK with Xcode 12 compatibility 36 | - Fixed macOS 10.8 compatibility (without ASPM support) 37 | 38 | #### v2.0.9 39 | - boot-arg and property `brcmfx-aspm` supports special value `255` in order to skip logic disabling APSM for 0x14e4:0x43a3 (DW1820A). 40 | It can be used if you have masked pin 53 (CLKREQ#) and APSM L0|L1 is working. 41 | - Improve service matching (the old implementation could cause hangs on boot) 42 | 43 | #### v2.0.8 44 | - Added constants for 11.0 support 45 | - Property `pci-aspm-default` with value 0 is not required for Broadcom BCM4350 chipset (with non-apple `subsystem-vendor-id`), 46 | since now it is injected/corrected and method IOPCIFamily::setASPMState called for provider to disable ASPM immediately. 47 | - Add required dependencies into OSBundleLibraries section 48 | - Remove injectors for AirPortBrcm4360 and AirPortBrcmNIC from main Info.plist and move them into separate plugins AirPortBrcm4360_Injector and 49 | AirPortBrcmNIC_Injector (kexts with plist only). 50 | Under 11.0 (Big Sur) plugin AirPortBrcm4360_Injector.kext must be blocked by MaxKernel 19.9.9 or just removed, otherwise it will block loading of AirPortBrcmNIC 51 | since class AirPortBrcm4360 is unsupported. 52 | - Check whether brcmfx-driver value is incorrect (if specified value is unsupported in current osx system) 53 | - Support boot-arg and property `brcmfx-aspm` to override value used for pci-aspm-default 54 | 55 | #### v2.0.7 56 | - Fix for kernel panic when FakeBrcm is detached from provider (provider->close(service)) 57 | 58 | #### v2.0.6 59 | - Add previous implementation of wowl disabler (both methods wlc_wowl_enable and wowCapablePlatform must be overridden) 60 | - Add support for DW1820A CN-096JNT & Fix freezing issues (thanks to Sniki) 61 | - Read property brcmfx-driver from provider's IOReg entry (can be injected by bootloader as well as brcmfx-country property) 62 | 63 | #### v2.0.5 64 | - Re-implement wowl disabler (fix bug #615) 65 | 66 | #### v2.0.4 67 | - Minor improvement in method findService (based on panic report analysis) 68 | - Do not use removeObject, use getNextObject 69 | 70 | #### v2.0.3 71 | - Unified binary archive names 72 | 73 | #### v2.0.2 74 | - Fixed compatibility with 10.15 75 | 76 | #### v2.0.1 77 | - Allow loading on 10.15 without `-lilubetaall` 78 | 79 | #### v2.0.0 80 | - checkBoardId patch has been improved: returns false for boardId in cpmChanSwitchWhitelist 81 | - Service provider name is changed to ARPT automatically 82 | 83 | #### v1.1.9 84 | - Fix issue with IOProbeScore for Airport_BrcmNIC 85 | 86 | #### v1.1.8 87 | - Support AirPort_Brcm4331 88 | 89 | #### v1.1.7 90 | - Use separate variables and methods wlc_set_countrycode_rev & siPmuFvcoPllreg for every driver 91 | - Introduce a new boot-arg brcmfx-driver=[0|1|2], 0 - AirPort.BrcmNIC-MFG, 1 - AirPort.Brcm4360, 2 - AirPort.BrcmNIC 92 | - Remove redundancy boot-args wl_msg_level and wl_msg_level2 (they are supported by Apple) 93 | - pci14e4,43b1 & pci14e4,43b2 matched also to AirPort_BrcmNIC 94 | 95 | #### v1.1.6 96 | - Try to resolve linker issue with __ZN13Configuration18bootargBrcmCountryE (with older Xcode versions) 97 | 98 | #### v1.1.5 99 | - Mojave compatible 100 | 101 | #### v1.1.4 102 | - Add patch to disable LPO panic in AirPortBrcmNIC: on some cards (DW1820A/BCM4350), the external LPO clock is sometimes 103 | not set upon initialization. While harmless in AirPortBrcm4360, AirPortBrcmNIC panics if this occurs. As it wasn't present previously, 104 | _osl_panic for string "32KHz LPO Clock not running" does not produce panic in AirPortBrcmNIC. Idea by al3xtjames. 105 | 106 | #### v1.1.3 107 | - Allow to load all matched drivers for broadcom wi-fi (in case if there is a concurrency), except AirPortBrcmNIC-MFG.kext 108 | - AirPortBrcmNIC-MFG probe & start are hooked to prevent using of this driver 109 | - Fix a name conflict for config variable 110 | 111 | #### v1.1.2 112 | - FakeBrcm is destroyed & removed from ioreg, there is no need to start original ariport driver, gIOCatalogue->removeDrivers called for FakeBrcm does this. 113 | 114 | #### v1.1.1 115 | - Cosmetic change 116 | 117 | #### v1.1.0 118 | - XCode 9 & Lilu 1.2.0 compatibility fixes (Lilu 1.2.0 is required) 119 | 120 | #### v.1.0.11 121 | - Fix co-existing with FakePCIID_Broadcom_WiFi.kext & FakePCIID 122 | 123 | #### v1.0.10 124 | - WOWL (WoWLAN) is disabled by default. Use boot-arg -brcmfxwowl to enable it. 125 | 126 | #### v1.0.9 127 | - Parameter brcmfx-country can be located in ioreg (in provider, ARPT for example) 128 | 129 | #### v1.0.8 130 | - 5 Ghz/country code patch fixed (low speed after wake up) 131 | 132 | #### v1.0.7 133 | - New boot-args: wl_msg_level=XXXXX and wl_msg_level2=XXXXX pass specified values to respective fields in driver, allows to get a full log 134 | - FakePCIID functionality is built-in 135 | 136 | #### v1.0.6 137 | - Pass property table to the newly created instance of a driver. Disable FakeBrcm if processKext was called earlier. 138 | 139 | #### v1.0.5 140 | - Fix for High Sierra Developer Beta 7 (loading order) 141 | 142 | #### v1.0.4 143 | - Bug in release version has been fixed (EXPORT added). 144 | - Debugging output was improved. 145 | 146 | #### v1.0.3 147 | - Don't use FakeBrcm under 10.13 and higher. 148 | 149 | #### v1.0.2 150 | - 5 Ghz/country code patch reimplemented. Boot arg brcmfx-country=XX is supported. 151 | 152 | #### v1.0.1 153 | - Refactoring, patch for "Failed PCIe configuration" added" 154 | - Patch for 5Ghz / Country code added 155 | - A new pseudo device FakeBrcm is introduced. It is started instead of original broadcom driver. Original driver is started in processKext. 156 | 157 | #### v1.0.0 158 | - Initial release 159 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, lvs1974 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AirportBrcmFixup 2 | ================== 3 | 4 | [![Build Status](https://github.com/acidanthera/AirportBrcmFixup/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/acidanthera/AirportBrcmFixup/actions) [![Scan Status](https://scan.coverity.com/projects/16401/badge.svg?flat=1)](https://scan.coverity.com/projects/16401) 5 | 6 | An open source kernel extension providing a set of patches required for non-native Airport Broadcom Wi-Fi cards. 7 | 8 | #### Notes 9 | Currently this kext requires macOS 10.10 or newer. 10 | 11 | Note: ***Debug version of Lilu.kext should be put in the same folder as AirportBrcmFixup! And they should be also used together!*** 12 | 13 | #### Features 14 | - Supports AirPort_Brcm4360, AirPort_BrcmNIC and AirPort_BrcmNIC_MFG 15 | - Implements patch for chip identificator checking (0xaa52), in <=10.12 it's required for successful driver starting 16 | - Implements patch for "Failed PCIe configuration patch", required for some cards 17 | - Implements patch for "Third Party Device" (returns vendor name "Apple") 18 | - Implements patch for removing of white-list check 19 | - Implements 5Ghz and country code patch (US by default) 20 | - Implements WOWL (WoWLAN) disabler (turned on by default) - no low speed after wake 21 | - Implements patch to disable LPO panic in AirPortBrcmNIC 22 | 23 | #### Installation types 24 | - Clover Airport Fix + AirportBrcmFixup 25 | - Clover Airport Fix + AddProperties(fake device-id) + AirportBrcmFixup (preferable) 26 | - Clover Airport Fix + AirportBrcmFixup + FakePCIID + FakePCIID_Broadcom_WiFi.kext 27 | - AirportBrcmFixup + FakePCIID + FakePCIID_Broadcom_WiFi.kext 28 | 29 | #### Boot-args 30 | - `-brcmfxdbg` turns on debugging output 31 | - `-brcmfxbeta` enables loading on unsupported osx 32 | - `-brcmfxoff` disables kext loading 33 | - `-brcmfxwowl` enables WOWL (WoWLAN) - it is disabled by default 34 | - `-brcmfx-alldrv` allows patching for all supported drivers, disregarding current system version (see `Matching device-id and kext name in different macOS versions`) 35 | 36 | #### Specific boot-args and ioreg properties 37 | - `brcmfx-country=XX` changes the country code to XX (US, CN, #a, ...), also can be injected via DSDT or Properties → DeviceProperties in bootloader 38 | - `brcmfx-aspm` overrides value used for pci-aspm-default 39 | - `brcmfx-wowl` enables/disables WoWLAN patch 40 | - `brcmfx-delay` delays start of native broadcom driver for specified amount of milliseconds. It can solve panics or missing wi-fi device in Monterey. You can start with 15 seconds (brcmfx-delay=15000) and successively reduce this value until you notice instability in boot. 41 | - `brcmfx-alldrv` allows patching for all supported drivers, disregarding current system version (see `Matching device-id and kext name in different macOS versions`) 42 | - `brcmfx-driver=0|1|2|3` enables only one kext for loading, 0 - AirPortBrcmNIC-MFG, 1 - AirPortBrcm4360, 2 - AirPortBrcmNIC, 3 - AirPortBrcm4331, also can be injected via DSDT or Properties → DeviceProperties in bootloader 43 | 44 | Possible values for brcmfx-aspm (and pci-aspm-default): 45 | - `0` disables ASPM 46 | - `kIOPCIExpressASPML0s` = 0x00000001, 47 | - `kIOPCIExpressASPML1` = 0x00000002, 48 | - `kIOPCIExpressCommonClk` = 0x00000040, 49 | - `kIOPCIExpressClkReq` = 0x00000100 50 | 51 | 52 | 53 | #### Credits 54 | - [Apple](https://www.apple.com) for macOS 55 | - [vit9696](https://github.com/vit9696) for [Lilu.kext](https://github.com/vit9696/Lilu) and great help in implementing some features 56 | - [PMheart](https://github.com/PMheart) for the initial idea and implementation 57 | - darkvoid & RehabMan for FakePCIID implementation (partly used in AirportBrcmFixup) 58 | - [al3xtjames](https://github.com/al3xtjames) for disabling LPO panic in AirPortBrcmNIC 59 | - [lvs1974](https://applelife.ru/members/lvs1974.53809/) for writing the software and maintaining it 60 | 61 | 62 | #### Matching device-id and kext name in different macOS versions 63 | [10.8] 64 | - AirPortBrcm4360: 43a0, IOProbeScore = 641 65 | - AirPortBrcm4331: 4331, 4353, 432b, IOProbeScore = 615 66 | 67 | [10.9] 68 | - AirPortBrcm4360: 43a0, IOProbeScore = 842 69 | - AirPortBrcm4331: 4331, 4353, 432b, IOProbeScore = 700 70 | 71 | [10.10] 72 | - AirPortBrcm4360: 43ba, 43a3, 43a0, 4331, 4353, IOProbeScore = 930 73 | - AirPortBrcm4331: 4331, 4353, 432b, IOProbeScore = 900 74 | 75 | [10.11] 76 | - AirPortBrcm4360: 43ba, 43a3, 43a0, 4331, 4353, IOProbeScore = 1040 77 | - AirPortBrcm4331: 4331, 4353, 432b, IOProbeScore = 800 78 | 79 | [10.12] 80 | - AirPortBrcm4360: 43ba, 43a3, 43a0, 4331, 4353, IOProbeScore = 1152 81 | - AirPortBrcm4331: 4331, 4353, 432b, IOProbeScore = 800 82 | 83 | [10.13] 84 | - AirPortBrcm4360: 4331, 4353, IOProbeScore = 1240 85 | - AirPortBrcm4331: 4331, 4353, 432b, IOProbeScore = 800 86 | - AirPortBrcmNIC: 43ba, 43a3, 43a0, IOProbeScore = 1241 87 | - AirPortBrcmNIC-MFG: 43ba, 43a3, 43a0, IOProbeScore = -1000 88 | 89 | [10.14] 90 | - AirPortBrcm4360: 4331, 4353, IOProbeScore = 1400 91 | - AirPortBrcm4331: 4331, 4353, 432b, IOProbeScore = 800 92 | - AirPortBrcmNIC: 43ba, 43a3, 43a0, IOProbeScore = 1400 93 | - AirPortBrcmNIC-MFG: 43ba, 43a3, 43a0, IOProbeScore = -1000 94 | 95 | [10.15] 96 | - AirPortBrcm4360: 4331, 4353, IOProbeScore = 1400 97 | - AirPortBrcm4331: removed 98 | - AirPortBrcmNIC: 43ba, 43a3, 43a0, IOProbeScore = 1400 99 | - AirPortBrcmNIC-MFG: removed 100 | 101 | [11] 102 | - AirPortBrcm4360: removed 103 | - AirPortBrcm4331: removed 104 | - AirPortBrcmNIC: 43ba, 43a3, 43a0, IOProbeScore = 1400 105 | - AirPortBrcmNIC-MFG: removed 106 | 107 | [12] 108 | - AirPortBrcm4360: removed 109 | - AirPortBrcm4331: removed 110 | - AirPortBrcmNIC: 43ba, 43a3, 43a0, IOProbeScore = 1400, kext is moved to the new location - IO80211FamilyLegacy.kext/Contents/PlugIns 111 | - AirPortBrcmNIC-MFG: removed 112 | 113 | [13] 114 | - AirPortBrcm4360: removed 115 | - AirPortBrcm4331: removed 116 | - AirPortBrcmNIC: 43ba, 43a3, 43a0, IOProbeScore = 1400, kext is moved to the new location - IO80211FamilyLegacy.kext/Contents/PlugIns 117 | - AirPortBrcmNIC-MFG: removed 118 | 119 | [14+] Use with OCLP 120 | - AirPortBrcm4360: removed 121 | - AirPortBrcm4331: removed 122 | - AirPortBrcmNIC: removed 123 | - AirPortBrcmNIC-MFG: removed 124 | 125 | Explanation in russian language: (https://applelife.ru/threads/airportbrcmfixup-lilu-plagin-s-naborom-patchej-dlja-wi-fi-kart-broadcom.2355103/page-16#post-751173) 126 | 127 | Until version [10.13] there were only two kexts and for the most cases FakeID = 43a0 was enough to get working Wi-Fi. 128 | In [10.13] (and later) one family was separated into AirPortBrcm4360 (probably will be removed in 10.15), AirPortBrcmNIC and AirPortBrcmNIC-MFG. 129 | A proper fake-id has to be considered to load appropriate kext. Some device-id have limitations in one kext (like 5 Ghz range), but do not have it another. 130 | 131 | #### Please pay attention 132 | In 11+ class AirPortBrcm4360 has been completely removed. Using of injector kext with such class name and matched ```vendor-id:device-id``` blocks 133 | loading of original airport kext. To address this issue and keep compatibility with older systems injectors for AirPortBrcm4360 and AirPortBrcmNIC were removed 134 | from main Info.plist file. Instead, the two new kext injectors are deployed in PlugIns folder: AirPortBrcm4360_Injector.kext and AirPortBrcmNIC_Injector.kext. 135 | ***You have to block (or remove) AirPortBrcm4360_Injector.kext in 11+.*** In OpenCore you can specify MaxKernel 19.9.9 for AirPortBrcm4360_Injector.kext. 136 | In Clover you can have two different AirportBrcmFixup.kext, but in kext folder with version name 11 and 12 and 13 AirportBrcmFixup.kext must not contain AirPortBrcm4360_Injector.kext. You don't need these injectors at all if your ```vendor-id:device-id``` is natively supported by AirPortBrcmNIC or AirPortBrcm4360 (your device-id is included into Info.plist in these kexts). 137 | 138 | -------------------------------------------------------------------------------- /Resources/AirPortBrcm4360_Injector.kext/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleGetInfoString 6 | Copyright © 2020 lvs1974. All rights reserved. 7 | CFBundleIdentifier 8 | as.lvs1974.AirportBrcm4360Injector 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | AirPortBrcm4360 13 | CFBundlePackageType 14 | KEXT 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0 21 | IOKitPersonalities 22 | 23 | Airport_Brcm4360 24 | 25 | CFBundleIdentifier 26 | com.apple.driver.AirPort.Brcm4360 27 | IOClass 28 | AirPort_Brcm4360 29 | IOMatchCategory 30 | IODefaultMatchCategory 31 | IONameMatch 32 | 33 | pci14e4,4331 34 | pci14e4,4353 35 | pci14e4,4357 36 | pci14e4,43a3 37 | pci14e4,43b1 38 | pci14e4,43b2 39 | 40 | IOProbeScore 41 | 1110 42 | IOProviderClass 43 | IOPCIDevice 44 | TruePowerOff 45 | 46 | 47 | 48 | OSBundleRequired 49 | Network-Root 50 | 51 | 52 | -------------------------------------------------------------------------------- /Resources/AirPortBrcmNIC_Injector.kext/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleGetInfoString 6 | Copyright © 2020 lvs1974. All rights reserved. 7 | CFBundleIdentifier 8 | as.lvs1974.AirportBrcmNICInjector 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | AirPortBrcmNIC 13 | CFBundlePackageType 14 | KEXT 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0 21 | IOKitPersonalities 22 | 23 | Airport_BrcmNIC 24 | 25 | CFBundleIdentifier 26 | com.apple.driver.AirPort.BrcmNIC 27 | IOClass 28 | AirPort_BrcmNIC 29 | IOMatchCategory 30 | IODefaultMatchCategory 31 | IONameMatch 32 | 33 | pci14e4,4331 34 | pci14e4,4353 35 | pci14e4,4357 36 | pci14e4,43ba 37 | pci14e4,43a3 38 | pci14e4,43a0 39 | pci14e4,43b1 40 | pci14e4,43b2 41 | 42 | IOProbeScore 43 | 2048 44 | IOProviderClass 45 | IOPCIDevice 46 | TruePowerOff 47 | 48 | 49 | 50 | OSBundleRequired 51 | Network-Root 52 | 53 | 54 | --------------------------------------------------------------------------------