├── .github └── workflows │ └── main.yml ├── .gitignore ├── Changelog.md ├── LICENSE.txt ├── README.md ├── RTCMemoryFixup.xcodeproj └── project.pbxproj └── RTCMemoryFixup ├── Info.plist ├── RTCMemoryFixup.cpp └── RTCMemoryFixup.hpp /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | workflow_dispatch: 7 | release: 8 | types: [published] 9 | 10 | env: 11 | PROJECT_TYPE: KEXT 12 | 13 | jobs: 14 | build: 15 | name: Build 16 | runs-on: macos-latest 17 | env: 18 | JOB_TYPE: BUILD 19 | steps: 20 | - uses: actions/checkout@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 RTCMemoryFixup -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 RTCMemoryFixup -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 | project.xcworkspace 6 | build 7 | xcshareddata 8 | /MacKernelSDK 9 | -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | RTCMemoryFixup Changelog 2 | ============================ 3 | #### v1.0.7 4 | - Added MacKernelSDK with Xcode 12 compatibility 5 | 6 | #### v.1.0.6 7 | - Fix reading of key rtc-blacklist from NVRAM (only 4 bytes could be read) 8 | - rtcfx_exclude can be combined with rtc-blacklist 9 | 10 | #### v1.0.5 11 | - Support key rtc-blacklist set by OpenCore in NVRAM 12 | 13 | #### v1.0.4 14 | - Unified release archive names 15 | 16 | #### v1.0.3 17 | - Fixed compiling and loading on older OS 18 | - Fixed loading from /Library/Extensions 19 | - rtcfx_exclude property is read as string from RTC provider's properties 20 | 21 | #### v1.0.2 22 | - Wrong range start value in debug message has been fixed (thanks to nms42) 23 | 24 | #### v1.0.1 25 | - Bug fix: prevent kext unloading 26 | 27 | #### v1.0.0 28 | - Initial release 29 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, 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 | RTCMemoryFixup 2 | ============== 3 | 4 | [![Build Status](https://github.com/acidanthera/RTCMemoryFixup/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/acidanthera/RTCMemoryFixup/actions) [![Scan Status](https://scan.coverity.com/projects/22195/badge.svg?flat=1)](https://scan.coverity.com/projects/22195) 5 | 6 | An open source kernel extension providing a way to emulate some offsets in CMOS (RTC) memory. It can help you to avoid some conflicts between macOS AppleRTC and firmware/BIOS of your PC. 7 | 8 | It can also help you to find out at which offsets you have a conflict. In most cases it is enough to boot with some offsets in boot-args, perform sleep, wake and reboot. If you don't see any CMOS errors or some unexpected reboots, it means you have managed to exclude conflicted CMOS offsets. 9 | 10 | Offsets in boot-args `rtcfx_exclude` can have value from 00 to FF (wihout prefix 0x). Be careful: 11 | 12 | - Offsets from 0 to 0D usually are more or less 'compatible' and should not cause any conflicts. 13 | - Offsets from 0x80 to 0xAB are used to store some hibernation information (IOHibernateRTCVariables). If any offset in this range causes a conflict, you can exclude it, but hibernation won't work. 14 | - In my case it was only the one offset: B2. B0 - B4 offsets are used for PowerManagement features, but they don't work on hacks anyway) 15 | 16 | #### Compilation 17 | - This kext is not Lilu-plugin, but it still relies on some useful methods from Lilu libraries, so you have to put Lilu.kext into project folder. 18 | 19 | #### Boot-args 20 | - `rtcfx_exclude=offset1,offset2,start_offset-end_offset...` - list of offsets or ranges of offsets where writing is not allowed 21 | - `-rtcfxdbg` turns on debugging output 22 | 23 | #### Credits 24 | - [Apple](https://www.apple.com) for macOS 25 | - [vit9696](https://github.com/vit9696) for [Lilu.kext](https://github.com/vit9696/Lilu) and great help in implementing some features 26 | - [lvs1974](https://applelife.ru/members/lvs1974.53809/) for writing the software and maintaining it 27 | 28 | 29 | -------------------------------------------------------------------------------- /RTCMemoryFixup.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | CE39539C244ECDD900DEFAEA /* plugin_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE405ED81E4A080700AA0B3D /* plugin_start.cpp */; }; 11 | CE8DA0CC2517DE74008C44E8 /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE8DA0CB2517DE74008C44E8 /* libkmod.a */; }; 12 | CEAAA50C21FC976100683764 /* RTCMemoryFixup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CEAAA50921FC976100683764 /* RTCMemoryFixup.cpp */; }; 13 | CEAAA50D21FC976100683764 /* RTCMemoryFixup.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CEAAA50A21FC976100683764 /* RTCMemoryFixup.hpp */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXCopyFilesBuildPhase section */ 17 | 1C642F521C8F157A006B4C51 /* CopyFiles */ = { 18 | isa = PBXCopyFilesBuildPhase; 19 | buildActionMask = 2147483647; 20 | dstPath = ""; 21 | dstSubfolderSpec = 13; 22 | files = ( 23 | ); 24 | runOnlyForDeploymentPostprocessing = 0; 25 | }; 26 | /* End PBXCopyFilesBuildPhase section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 1C748C271C21952C0024EED2 /* RTCMemoryFixup.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RTCMemoryFixup.kext; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 1CF01C901C8CF97F002DCEA3 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 31 | 1CF01C921C8CF997002DCEA3 /* Changelog.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Changelog.md; sourceTree = ""; }; 32 | 1CF01C931C8DF02E002DCEA3 /* LICENSE.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; }; 33 | CE405EBA1E49DD7100AA0B3D /* kern_compression.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_compression.hpp; sourceTree = ""; }; 34 | CE405EBB1E49DD7100AA0B3D /* kern_disasm.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_disasm.hpp; sourceTree = ""; }; 35 | CE405EBC1E49DD7100AA0B3D /* kern_file.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_file.hpp; sourceTree = ""; }; 36 | CE405EBD1E49DD7100AA0B3D /* kern_iokit.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_iokit.hpp; sourceTree = ""; }; 37 | CE405EBE1E49DD7100AA0B3D /* kern_mach.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_mach.hpp; sourceTree = ""; }; 38 | CE405EBF1E49DD7100AA0B3D /* kern_patcher.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_patcher.hpp; sourceTree = ""; }; 39 | CE405EC01E49DD7100AA0B3D /* kern_policy.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_policy.hpp; sourceTree = ""; }; 40 | CE405EC31E49DD7100AA0B3D /* kern_user.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_user.hpp; sourceTree = ""; }; 41 | CE405EC41E49DD7100AA0B3D /* kern_util.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_util.hpp; sourceTree = ""; }; 42 | CE405ECF1E49EC9100AA0B3D /* kern_config.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = kern_config.hpp; sourceTree = ""; }; 43 | CE405ED21E49F9FC00AA0B3D /* kern_api.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_api.hpp; sourceTree = ""; }; 44 | CE405ED81E4A080700AA0B3D /* plugin_start.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = plugin_start.cpp; sourceTree = ""; }; 45 | CE405EDA1E4A080F00AA0B3D /* plugin_start.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = plugin_start.hpp; sourceTree = ""; }; 46 | CE8DA0CB2517DE74008C44E8 /* libkmod.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libkmod.a; path = ../Lilu/MacKernelSDK/Library/x86_64/libkmod.a; sourceTree = ""; }; 47 | CEAAA50821FC976100683764 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 48 | CEAAA50921FC976100683764 /* RTCMemoryFixup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RTCMemoryFixup.cpp; sourceTree = ""; }; 49 | CEAAA50A21FC976100683764 /* RTCMemoryFixup.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RTCMemoryFixup.hpp; sourceTree = ""; }; 50 | /* End PBXFileReference section */ 51 | 52 | /* Begin PBXFrameworksBuildPhase section */ 53 | 1C748C231C21952C0024EED2 /* Frameworks */ = { 54 | isa = PBXFrameworksBuildPhase; 55 | buildActionMask = 2147483647; 56 | files = ( 57 | CE8DA0CC2517DE74008C44E8 /* libkmod.a in Frameworks */, 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | 1C748C1D1C21952C0024EED2 = { 65 | isa = PBXGroup; 66 | children = ( 67 | CEAAA50721FC976100683764 /* RTCMemoryFixup */, 68 | 1CF01C911C8CF982002DCEA3 /* Docs */, 69 | CE405EC81E49DD7B00AA0B3D /* SDK */, 70 | 1C748C281C21952C0024EED2 /* Products */, 71 | CE8DA0CA2517DE74008C44E8 /* Frameworks */, 72 | ); 73 | sourceTree = ""; 74 | }; 75 | 1C748C281C21952C0024EED2 /* Products */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 1C748C271C21952C0024EED2 /* RTCMemoryFixup.kext */, 79 | ); 80 | name = Products; 81 | sourceTree = ""; 82 | }; 83 | 1CF01C911C8CF982002DCEA3 /* Docs */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | 1CF01C901C8CF97F002DCEA3 /* README.md */, 87 | 1CF01C931C8DF02E002DCEA3 /* LICENSE.txt */, 88 | 1CF01C921C8CF997002DCEA3 /* Changelog.md */, 89 | ); 90 | name = Docs; 91 | sourceTree = ""; 92 | }; 93 | CE405EB91E49DD7100AA0B3D /* Headers */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | CE405ED21E49F9FC00AA0B3D /* kern_api.hpp */, 97 | CE405ECF1E49EC9100AA0B3D /* kern_config.hpp */, 98 | CE405EBA1E49DD7100AA0B3D /* kern_compression.hpp */, 99 | CE405EBB1E49DD7100AA0B3D /* kern_disasm.hpp */, 100 | CE405EBC1E49DD7100AA0B3D /* kern_file.hpp */, 101 | CE405EBD1E49DD7100AA0B3D /* kern_iokit.hpp */, 102 | CE405EBE1E49DD7100AA0B3D /* kern_mach.hpp */, 103 | CE405EBF1E49DD7100AA0B3D /* kern_patcher.hpp */, 104 | CE405EC01E49DD7100AA0B3D /* kern_policy.hpp */, 105 | CE405EC31E49DD7100AA0B3D /* kern_user.hpp */, 106 | CE405EC41E49DD7100AA0B3D /* kern_util.hpp */, 107 | CE405EDA1E4A080F00AA0B3D /* plugin_start.hpp */, 108 | ); 109 | name = Headers; 110 | path = Lilu.kext/Contents/Resources/Headers; 111 | sourceTree = SOURCE_ROOT; 112 | }; 113 | CE405EC51E49DD7100AA0B3D /* Library */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | CE405ED81E4A080700AA0B3D /* plugin_start.cpp */, 117 | ); 118 | name = Library; 119 | path = Lilu.kext/Contents/Resources/Library; 120 | sourceTree = SOURCE_ROOT; 121 | }; 122 | CE405EC81E49DD7B00AA0B3D /* SDK */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | CE405EB91E49DD7100AA0B3D /* Headers */, 126 | CE405EC51E49DD7100AA0B3D /* Library */, 127 | ); 128 | name = SDK; 129 | sourceTree = ""; 130 | }; 131 | CE8DA0CA2517DE74008C44E8 /* Frameworks */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | CE8DA0CB2517DE74008C44E8 /* libkmod.a */, 135 | ); 136 | name = Frameworks; 137 | sourceTree = ""; 138 | }; 139 | CEAAA50721FC976100683764 /* RTCMemoryFixup */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | CEAAA50821FC976100683764 /* Info.plist */, 143 | CEAAA50921FC976100683764 /* RTCMemoryFixup.cpp */, 144 | CEAAA50A21FC976100683764 /* RTCMemoryFixup.hpp */, 145 | ); 146 | path = RTCMemoryFixup; 147 | sourceTree = ""; 148 | }; 149 | /* End PBXGroup section */ 150 | 151 | /* Begin PBXHeadersBuildPhase section */ 152 | 1C748C241C21952C0024EED2 /* Headers */ = { 153 | isa = PBXHeadersBuildPhase; 154 | buildActionMask = 2147483647; 155 | files = ( 156 | CEAAA50D21FC976100683764 /* RTCMemoryFixup.hpp in Headers */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXHeadersBuildPhase section */ 161 | 162 | /* Begin PBXNativeTarget section */ 163 | 1C748C261C21952C0024EED2 /* RTCMemoryFixup */ = { 164 | isa = PBXNativeTarget; 165 | buildConfigurationList = 1C748C311C21952C0024EED2 /* Build configuration list for PBXNativeTarget "RTCMemoryFixup" */; 166 | buildPhases = ( 167 | 1C748C221C21952C0024EED2 /* Sources */, 168 | 1C748C231C21952C0024EED2 /* Frameworks */, 169 | 1C748C241C21952C0024EED2 /* Headers */, 170 | 1C748C251C21952C0024EED2 /* Resources */, 171 | 1C642F521C8F157A006B4C51 /* CopyFiles */, 172 | F6AC609B2052C75D00376609 /* Archive */, 173 | ); 174 | buildRules = ( 175 | ); 176 | dependencies = ( 177 | ); 178 | name = RTCMemoryFixup; 179 | productName = HibernationFixup; 180 | productReference = 1C748C271C21952C0024EED2 /* RTCMemoryFixup.kext */; 181 | productType = "com.apple.product-type.kernel-extension"; 182 | }; 183 | /* End PBXNativeTarget section */ 184 | 185 | /* Begin PBXProject section */ 186 | 1C748C1E1C21952C0024EED2 /* Project object */ = { 187 | isa = PBXProject; 188 | attributes = { 189 | LastUpgradeCheck = 1200; 190 | ORGANIZATIONNAME = vit9696; 191 | TargetAttributes = { 192 | 1C748C261C21952C0024EED2 = { 193 | CreatedOnToolsVersion = 7.2; 194 | }; 195 | }; 196 | }; 197 | buildConfigurationList = 1C748C211C21952C0024EED2 /* Build configuration list for PBXProject "RTCMemoryFixup" */; 198 | compatibilityVersion = "Xcode 3.2"; 199 | developmentRegion = en; 200 | hasScannedForEncodings = 0; 201 | knownRegions = ( 202 | en, 203 | Base, 204 | ); 205 | mainGroup = 1C748C1D1C21952C0024EED2; 206 | productRefGroup = 1C748C281C21952C0024EED2 /* Products */; 207 | projectDirPath = ""; 208 | projectRoot = ""; 209 | targets = ( 210 | 1C748C261C21952C0024EED2 /* RTCMemoryFixup */, 211 | ); 212 | }; 213 | /* End PBXProject section */ 214 | 215 | /* Begin PBXResourcesBuildPhase section */ 216 | 1C748C251C21952C0024EED2 /* Resources */ = { 217 | isa = PBXResourcesBuildPhase; 218 | buildActionMask = 2147483647; 219 | files = ( 220 | ); 221 | runOnlyForDeploymentPostprocessing = 0; 222 | }; 223 | /* End PBXResourcesBuildPhase section */ 224 | 225 | /* Begin PBXShellScriptBuildPhase section */ 226 | F6AC609B2052C75D00376609 /* Archive */ = { 227 | isa = PBXShellScriptBuildPhase; 228 | buildActionMask = 2147483647; 229 | files = ( 230 | ); 231 | inputPaths = ( 232 | ); 233 | name = Archive; 234 | outputPaths = ( 235 | ); 236 | runOnlyForDeploymentPostprocessing = 0; 237 | shellPath = /bin/sh; 238 | 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\nzip -qry -FS \"${archive}\" \"${dist[@]}\"\n"; 239 | }; 240 | /* End PBXShellScriptBuildPhase section */ 241 | 242 | /* Begin PBXSourcesBuildPhase section */ 243 | 1C748C221C21952C0024EED2 /* Sources */ = { 244 | isa = PBXSourcesBuildPhase; 245 | buildActionMask = 2147483647; 246 | files = ( 247 | CEAAA50C21FC976100683764 /* RTCMemoryFixup.cpp in Sources */, 248 | CE39539C244ECDD900DEFAEA /* plugin_start.cpp in Sources */, 249 | ); 250 | runOnlyForDeploymentPostprocessing = 0; 251 | }; 252 | /* End PBXSourcesBuildPhase section */ 253 | 254 | /* Begin XCBuildConfiguration section */ 255 | 1C748C2F1C21952C0024EED2 /* Debug */ = { 256 | isa = XCBuildConfiguration; 257 | buildSettings = { 258 | ALWAYS_SEARCH_USER_PATHS = NO; 259 | ARCHS = x86_64; 260 | CLANG_CXX_LANGUAGE_STANDARD = "c++1y"; 261 | CLANG_CXX_LIBRARY = "libc++"; 262 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 263 | CLANG_WARN_BOOL_CONVERSION = YES; 264 | CLANG_WARN_COMMA = YES; 265 | CLANG_WARN_CONSTANT_CONVERSION = YES; 266 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 267 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 268 | CLANG_WARN_EMPTY_BODY = YES; 269 | CLANG_WARN_ENUM_CONVERSION = YES; 270 | CLANG_WARN_INFINITE_RECURSION = YES; 271 | CLANG_WARN_INT_CONVERSION = YES; 272 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 273 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 274 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 275 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 276 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 277 | CLANG_WARN_STRICT_PROTOTYPES = YES; 278 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 279 | CLANG_WARN_UNREACHABLE_CODE = YES; 280 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 281 | DEBUG_INFORMATION_FORMAT = dwarf; 282 | ENABLE_STRICT_OBJC_MSGSEND = YES; 283 | ENABLE_TESTABILITY = YES; 284 | GCC_C_LANGUAGE_STANDARD = c11; 285 | GCC_NO_COMMON_BLOCKS = YES; 286 | GCC_OPTIMIZATION_LEVEL = 0; 287 | GCC_PREPROCESSOR_DEFINITIONS = ( 288 | "DEBUG=1", 289 | "$(inherited)", 290 | ); 291 | GCC_SYMBOLS_PRIVATE_EXTERN = YES; 292 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 293 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 294 | GCC_WARN_UNDECLARED_SELECTOR = YES; 295 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 296 | GCC_WARN_UNUSED_FUNCTION = YES; 297 | GCC_WARN_UNUSED_VARIABLE = YES; 298 | KERNEL_EXTENSION_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; 299 | KERNEL_FRAMEWORK_HEADERS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; 300 | ONLY_ACTIVE_ARCH = YES; 301 | SDKROOT = macosx; 302 | }; 303 | name = Debug; 304 | }; 305 | 1C748C301C21952C0024EED2 /* Release */ = { 306 | isa = XCBuildConfiguration; 307 | buildSettings = { 308 | ALWAYS_SEARCH_USER_PATHS = NO; 309 | ARCHS = x86_64; 310 | CLANG_CXX_LANGUAGE_STANDARD = "c++1y"; 311 | CLANG_CXX_LIBRARY = "libc++"; 312 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 313 | CLANG_WARN_BOOL_CONVERSION = YES; 314 | CLANG_WARN_COMMA = YES; 315 | CLANG_WARN_CONSTANT_CONVERSION = YES; 316 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 317 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 318 | CLANG_WARN_EMPTY_BODY = YES; 319 | CLANG_WARN_ENUM_CONVERSION = YES; 320 | CLANG_WARN_INFINITE_RECURSION = YES; 321 | CLANG_WARN_INT_CONVERSION = YES; 322 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 323 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 324 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 325 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 326 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 327 | CLANG_WARN_STRICT_PROTOTYPES = YES; 328 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 329 | CLANG_WARN_UNREACHABLE_CODE = YES; 330 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 331 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 332 | ENABLE_STRICT_OBJC_MSGSEND = YES; 333 | GCC_C_LANGUAGE_STANDARD = c11; 334 | GCC_NO_COMMON_BLOCKS = YES; 335 | GCC_OPTIMIZATION_LEVEL = 3; 336 | GCC_PREPROCESSOR_DEFINITIONS = ""; 337 | GCC_SYMBOLS_PRIVATE_EXTERN = YES; 338 | GCC_UNROLL_LOOPS = YES; 339 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 340 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 341 | GCC_WARN_UNDECLARED_SELECTOR = YES; 342 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 343 | GCC_WARN_UNUSED_FUNCTION = YES; 344 | GCC_WARN_UNUSED_VARIABLE = YES; 345 | KERNEL_EXTENSION_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; 346 | KERNEL_FRAMEWORK_HEADERS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; 347 | SDKROOT = macosx; 348 | }; 349 | name = Release; 350 | }; 351 | 1C748C321C21952C0024EED2 /* Debug */ = { 352 | isa = XCBuildConfiguration; 353 | buildSettings = { 354 | CLANG_ENABLE_OBJC_WEAK = YES; 355 | COPY_PHASE_STRIP = NO; 356 | CURRENT_PROJECT_VERSION = "$(MODULE_VERSION)"; 357 | DEPLOYMENT_POSTPROCESSING = YES; 358 | GCC_ENABLE_FLOATING_POINT_LIBRARY_CALLS = NO; 359 | GCC_ENABLE_KERNEL_DEVELOPMENT = NO; 360 | GCC_GENERATE_DEBUGGING_SYMBOLS = NO; 361 | GCC_PREPROCESSOR_DEFINITIONS = ( 362 | "MODULE_VERSION=$(MODULE_VERSION)", 363 | "PRODUCT_NAME=$(PRODUCT_NAME)", 364 | "LILU_CUSTOM_IOKIT_INIT=1", 365 | "LILU_CUSTOM_KMOD_INIT=1", 366 | "$(inherited)", 367 | ); 368 | HEADER_SEARCH_PATHS = "${PROJECT_DIR}/Lilu.kext/Contents/Resources"; 369 | INFOPLIST_FILE = RTCMemoryFixup/Info.plist; 370 | LIBRARY_SEARCH_PATHS = ( 371 | "$(inherited)", 372 | "$(PROJECT_DIR)/MacKernelSDK/Library/x86_64", 373 | ); 374 | MACOSX_DEPLOYMENT_TARGET = 10.8; 375 | MODULE_NAME = as.lvs1974.RTCMemoryFixup; 376 | MODULE_VERSION = 1.0.8; 377 | OTHER_CFLAGS = ( 378 | "-mmmx", 379 | "-msse", 380 | "-msse2", 381 | "-msse3", 382 | "-mfpmath=sse", 383 | "-mssse3", 384 | "-ftree-vectorize", 385 | "-fno-non-call-exceptions", 386 | "-fno-builtin", 387 | "-fno-asynchronous-unwind-tables", 388 | "-Wno-unknown-warning-option", 389 | "-Wno-ossharedptr-misuse", 390 | "-Wno-vla", 391 | ); 392 | OTHER_LDFLAGS = "-static"; 393 | PRODUCT_BUNDLE_IDENTIFIER = "$(MODULE_NAME)"; 394 | PRODUCT_NAME = "$(TARGET_NAME)"; 395 | WRAPPER_EXTENSION = kext; 396 | }; 397 | name = Debug; 398 | }; 399 | 1C748C331C21952C0024EED2 /* Release */ = { 400 | isa = XCBuildConfiguration; 401 | buildSettings = { 402 | CLANG_ENABLE_OBJC_WEAK = YES; 403 | CURRENT_PROJECT_VERSION = "$(MODULE_VERSION)"; 404 | DEAD_CODE_STRIPPING = YES; 405 | DEPLOYMENT_POSTPROCESSING = YES; 406 | GCC_ENABLE_FLOATING_POINT_LIBRARY_CALLS = NO; 407 | GCC_ENABLE_KERNEL_DEVELOPMENT = NO; 408 | GCC_GENERATE_DEBUGGING_SYMBOLS = YES; 409 | GCC_PREPROCESSOR_DEFINITIONS = ( 410 | "MODULE_VERSION=$(MODULE_VERSION)", 411 | "PRODUCT_NAME=$(PRODUCT_NAME)", 412 | "LILU_CUSTOM_IOKIT_INIT=1", 413 | "LILU_CUSTOM_KMOD_INIT=1", 414 | ); 415 | HEADER_SEARCH_PATHS = "${PROJECT_DIR}/Lilu.kext/Contents/Resources"; 416 | INFOPLIST_FILE = RTCMemoryFixup/Info.plist; 417 | LIBRARY_SEARCH_PATHS = ( 418 | "$(inherited)", 419 | "$(PROJECT_DIR)/MacKernelSDK/Library/x86_64", 420 | ); 421 | LLVM_LTO = YES; 422 | MACOSX_DEPLOYMENT_TARGET = 10.8; 423 | MODULE_NAME = as.lvs1974.RTCMemoryFixup; 424 | MODULE_VERSION = 1.0.8; 425 | OTHER_CFLAGS = ( 426 | "-mmmx", 427 | "-msse", 428 | "-msse2", 429 | "-msse3", 430 | "-mfpmath=sse", 431 | "-mssse3", 432 | "-ftree-vectorize", 433 | "-fno-non-call-exceptions", 434 | "-fno-builtin", 435 | "-fno-asynchronous-unwind-tables", 436 | "-Wno-unknown-warning-option", 437 | "-Wno-ossharedptr-misuse", 438 | "-Wno-vla", 439 | ); 440 | OTHER_LDFLAGS = "-static"; 441 | PRODUCT_BUNDLE_IDENTIFIER = "$(MODULE_NAME)"; 442 | PRODUCT_NAME = "$(TARGET_NAME)"; 443 | STRIP_STYLE = "non-global"; 444 | WRAPPER_EXTENSION = kext; 445 | }; 446 | name = Release; 447 | }; 448 | /* End XCBuildConfiguration section */ 449 | 450 | /* Begin XCConfigurationList section */ 451 | 1C748C211C21952C0024EED2 /* Build configuration list for PBXProject "RTCMemoryFixup" */ = { 452 | isa = XCConfigurationList; 453 | buildConfigurations = ( 454 | 1C748C2F1C21952C0024EED2 /* Debug */, 455 | 1C748C301C21952C0024EED2 /* Release */, 456 | ); 457 | defaultConfigurationIsVisible = 0; 458 | defaultConfigurationName = Release; 459 | }; 460 | 1C748C311C21952C0024EED2 /* Build configuration list for PBXNativeTarget "RTCMemoryFixup" */ = { 461 | isa = XCConfigurationList; 462 | buildConfigurations = ( 463 | 1C748C321C21952C0024EED2 /* Debug */, 464 | 1C748C331C21952C0024EED2 /* Release */, 465 | ); 466 | defaultConfigurationIsVisible = 0; 467 | defaultConfigurationName = Release; 468 | }; 469 | /* End XCConfigurationList section */ 470 | }; 471 | rootObject = 1C748C1E1C21952C0024EED2 /* Project object */; 472 | } 473 | -------------------------------------------------------------------------------- /RTCMemoryFixup/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OSBundleRequired 6 | Root 7 | CFBundleDevelopmentRegion 8 | $(DEVELOPMENT_LANGUAGE) 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | KEXT 19 | CFBundleShortVersionString 20 | $(MODULE_VERSION) 21 | CFBundleVersion 22 | $(MODULE_VERSION) 23 | IOKitPersonalities 24 | 25 | as.lvs1974.RTCMemoryFixup 26 | 27 | CFBundleIdentifier 28 | $(PRODUCT_BUNDLE_IDENTIFIER) 29 | IOClass 30 | RTCMemoryFixup 31 | IONameMatch 32 | PNP0B00 33 | IOProbeScore 34 | 100 35 | IOProviderClass 36 | IOACPIPlatformDevice 37 | 38 | 39 | NSHumanReadableCopyright 40 | Copyright © 2018 lvs1974. All rights reserved. 41 | OSBundleCompatibleVersion 42 | 1.0 43 | OSBundleLibraries 44 | 45 | com.apple.kpi.mach 46 | 12.0.0 47 | com.apple.kpi.libkern 48 | 12.0.0 49 | com.apple.kpi.iokit 50 | 12.0.0 51 | com.apple.kpi.dsep 52 | 12.0.0 53 | com.apple.kpi.bsd 54 | 12.0.0 55 | com.apple.kpi.unsupported 56 | 12.0.0 57 | as.vit9696.Lilu 58 | 1.2.0 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /RTCMemoryFixup/RTCMemoryFixup.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // RTCMemoryFixup.cpp 3 | // RTCMemoryFixup 4 | // 5 | // Copyright © 2020 lvs1974. All rights reserved. 6 | // 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "RTCMemoryFixup.hpp" 14 | 15 | #define RTC_ADDRESS_SECONDS 0x00 // R/W Range 0..59 16 | #define RTC_ADDRESS_SECONDS_ALARM 0x01 // R/W Range 0..59 17 | #define RTC_ADDRESS_MINUTES 0x02 // R/W Range 0..59 18 | #define RTC_ADDRESS_MINUTES_ALARM 0x03 // R/W Range 0..59 19 | #define RTC_ADDRESS_HOURS 0x04 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM 20 | #define RTC_ADDRESS_HOURS_ALARM 0x05 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM 21 | #define RTC_ADDRESS_DAY_OF_THE_WEEK 0x06 // R/W Range 1..7 22 | #define RTC_ADDRESS_DAY_OF_THE_MONTH 0x07 // R/W Range 1..31 23 | #define RTC_ADDRESS_MONTH 0x08 // R/W Range 1..12 24 | #define RTC_ADDRESS_YEAR 0x09 // R/W Range 0..99 25 | #define RTC_ADDRESS_REGISTER_A 0x0A // R/W[0..6] R0[7] 26 | #define RTC_ADDRESS_REGISTER_B 0x0B // R/W 27 | #define RTC_ADDRESS_REGISTER_C 0x0C // RO 28 | #define RTC_ADDRESS_REGISTER_D 0x0D // RO 29 | 30 | // May be set to 01 FE /usr/libexec/efiupdater, which is DefaultBackgroundColor 31 | #define APPLERTC_BG_COLOUR_ADDR1 0x30 32 | #define APPLERTC_BG_COLOUR_ADDR2 0x31 33 | 34 | #define APPLERTC_HASHED_ADDR 0x0E // Checksum is calculated starting from this address. 35 | #define APPLERTC_TOTAL_SIZE 0x100 // All Apple hardware cares about 256 bytes of RTC memory 36 | #define APPLERTC_CHECKSUM_ADDR1 0x58 37 | #define APPLERTC_CHECKSUM_ADDR2 0x59 38 | 39 | #define APPLERTC_BOOT_STATUS_ADDR 0x5C // 0x5 - Exit Boot Services, 0x4 - recovery? (AppleBds.efi) 40 | 41 | #define APPLERTC_HIBERNATION_KEY_ADDR 0x80 // Contents of IOHibernateRTCVariables 42 | #define APPLERTC_HIBERNATION_KEY_LEN 0x2C // sizeof (AppleRTCHibernateVars) 43 | 44 | // 0x00 - after memory check if AppleSmcIo and AppleRtcRam are present (AppleBds.efi) 45 | // 0x02 - when blessing to recovery for EFI firmware update (closed source bless) 46 | #define APPLERTC_BLESS_BOOT_TARGET 0xAC // used for boot overrides at Apple 47 | #define APPLERTC_RECOVERYCHECK_STATUS 0xAF // 0x0 - at booting into recovery? connected to 0x5C 48 | 49 | #define APPLERTC_POWER_BYTES_ADDR 0xB0 // used by /usr/bin/pmset 50 | // Valid values could be found in stringForPMCode (https://opensource.apple.com/source/PowerManagement/PowerManagement-494.30.1/pmconfigd/PrivateLib.c.auto.html) 51 | #define APPLERTC_POWER_BYTE_PM_ADDR 0xB4 // special PM byte describing Power State 52 | #define APPLERTC_POWER_BYTES_LEN 0x08 53 | 54 | static constexpr const char *OcRtcBlacklistKey {NVRAM_PREFIX(LILU_VENDOR_GUID, "rtc-blacklist")}; 55 | static constexpr const char16_t *OcRtcBlacklistKeyEfi {u"rtc-blacklist"}; 56 | 57 | OSDefineMetaClassAndStructors(RTCMemoryFixup, IOService); 58 | 59 | RTCMemoryFixup::t_io_read8 RTCMemoryFixup::orgIoRead8 {nullptr}; 60 | RTCMemoryFixup::t_io_write8 RTCMemoryFixup::orgIoWrite8 {nullptr}; 61 | 62 | UInt16 RTCMemoryFixup::cmd_reg {0xFFFF}; 63 | UInt16 RTCMemoryFixup::cmd_offset {0xFFFF}; 64 | 65 | UInt8 RTCMemoryFixup::emulated_rtc_mem[RTC_SIZE] {}; 66 | bool RTCMemoryFixup::emulated_flag[RTC_SIZE] {}; 67 | 68 | //============================================================================== 69 | 70 | bool RTCMemoryFixup::init(OSDictionary *propTable) 71 | { 72 | ADDPR(debugEnabled) = checkKernelArgument("-rtcfxdbg") || checkKernelArgument("-liludbgall"); 73 | PE_parse_boot_argn("liludelay", &ADDPR(debugPrintDelay), sizeof(ADDPR(debugPrintDelay))); 74 | 75 | DBGLOG("RTCFX", "RTCMemoryFixup::init()"); 76 | 77 | bool ret = super::init(propTable); 78 | if (!ret) 79 | { 80 | SYSLOG("RTCFX", "RTCMemoryFixup super::init returned false\n"); 81 | return false; 82 | } 83 | 84 | memset(emulated_rtc_mem, 0, sizeof(emulated_rtc_mem)); 85 | memset(emulated_flag, 0, sizeof(emulated_flag)); 86 | 87 | return true; 88 | } 89 | 90 | //============================================================================== 91 | 92 | bool RTCMemoryFixup::attach(IOService *provider) 93 | { 94 | hookProvider(provider); 95 | return super::attach(provider); 96 | } 97 | 98 | //============================================================================== 99 | 100 | IOService* RTCMemoryFixup::probe(IOService * provider, SInt32 *score) 101 | { 102 | DBGLOG("RTCFX", "RTCMemoryFixup::probe()"); 103 | 104 | IOService* ret = super::probe(provider, score); 105 | if (!ret) 106 | { 107 | SYSLOG("RTCFX", "RTCMemoryFixup super::probe returned nullptr\n"); 108 | return nullptr; 109 | } 110 | 111 | *score = 20000; 112 | 113 | DBGLOG("RTCFX", "RTCMemoryFixup::probe(): service provider is %s", provider->getName()); 114 | 115 | return ret; 116 | } 117 | 118 | //============================================================================== 119 | 120 | bool RTCMemoryFixup::start(IOService *provider) 121 | { 122 | DBGLOG("RTCFX", "RTCMemoryFixup::start()"); 123 | 124 | if (!super::start(provider)) 125 | { 126 | SYSLOG("RTCFX", "RTCMemoryFixup super::start returned false\n"); 127 | return false; 128 | } 129 | 130 | retain(); 131 | 132 | hookProvider(provider); 133 | 134 | return false; 135 | } 136 | 137 | //============================================================================== 138 | 139 | void RTCMemoryFixup::stop(IOService *provider) 140 | { 141 | DBGLOG("RTCFX", "RTCMemoryFixup::stop() ignored"); 142 | //super::stop(provider); 143 | } 144 | 145 | //============================================================================== 146 | 147 | void RTCMemoryFixup::free() 148 | { 149 | DBGLOG("RTCFX", "RTCMemoryFixup::free() ignored"); 150 | //super::free(); 151 | } 152 | 153 | //============================================================================== 154 | 155 | UInt8 RTCMemoryFixup::ioRead8(IOService * that, UInt16 offset, IOMemoryMap * map) 156 | { 157 | UInt8 result = orgIoRead8(that, offset, map); 158 | 159 | if (offset != CMOS_DATAREG1 && offset != CMOS_DATAREG2) 160 | return result; 161 | 162 | if (cmd_reg == CMOS_ADDREG1 || cmd_reg == CMOS_ADDREG2) 163 | { 164 | //DBGLOG("RTCFX", "RTCMemoryFixup::ioRead8 read cmd_reg = %02X, cmd_offset = %02X, offset = %02X", cmd_reg, cmd_offset, offset); 165 | int safe_offset = (cmd_reg == CMOS_ADDREG2) ? 0x80 : 0; 166 | safe_offset += (cmd_offset & 0x7F); 167 | if (emulated_flag[safe_offset]) 168 | { 169 | result = emulated_rtc_mem[safe_offset]; 170 | } 171 | cmd_reg = 0xFFFF; 172 | } 173 | else 174 | { 175 | //DBGLOG("RTCFX", "RTCMemoryFixup::ioRead8 unexpected values: cmd_reg = %02X, cmd_offset = %02X, offset = %02X", cmd_reg, cmd_offset, offset); 176 | } 177 | 178 | return result; 179 | } 180 | 181 | //============================================================================== 182 | 183 | void RTCMemoryFixup::ioWrite8(IOService * that, UInt16 offset, UInt8 value, IOMemoryMap * map) 184 | { 185 | if (offset != CMOS_ADDREG1 && offset != CMOS_DATAREG1 && offset != CMOS_ADDREG2 && offset != CMOS_DATAREG2) 186 | { 187 | orgIoWrite8(that, offset, value, map); 188 | return; 189 | } 190 | 191 | bool write_enabled = true; 192 | if (offset == CMOS_ADDREG1 || offset == CMOS_ADDREG2) 193 | { 194 | cmd_reg = offset; 195 | cmd_offset = value; 196 | //DBGLOG("RTCFX", "RTCMemoryFixup::ioWrite8 request cmd_reg = %02X, cmd_offset = %02X", cmd_reg, cmd_offset); 197 | } 198 | else if (cmd_reg != 0xFFFF) 199 | { 200 | if ((cmd_reg == CMOS_ADDREG1 && offset == CMOS_DATAREG1) || (cmd_reg == CMOS_ADDREG2 && offset == CMOS_DATAREG2)) 201 | { 202 | int safe_offset = (cmd_reg == CMOS_ADDREG2) ? 0x80 : 0; 203 | safe_offset += (cmd_offset & 0x7F); 204 | if (emulated_flag[safe_offset]) 205 | { 206 | emulated_rtc_mem[safe_offset] = value; 207 | write_enabled = false; 208 | //DBGLOG("RTCFX", "RTCMemoryFixup::ioWrite8 rejects write to cmd_reg = %02X, cmd_offset = %02X, offset = %02X, value = %02X", cmd_reg, cmd_offset, offset, value); 209 | } 210 | } 211 | 212 | cmd_reg = 0xFFFF; 213 | } 214 | 215 | if (write_enabled) 216 | orgIoWrite8(that, offset, value, map); 217 | else 218 | orgIoRead8(that, value, map); 219 | } 220 | 221 | //============================================================================== 222 | 223 | bool RTCMemoryFixup::excludeAddresses(char* rtcfx_exclude) 224 | { 225 | bool result = false; 226 | char *tok = rtcfx_exclude, *end = rtcfx_exclude; 227 | char *dash = nullptr; 228 | while (tok != nullptr) 229 | { 230 | strsep(&end, ","); 231 | DBGLOG("RTCFX", "rtc offset token = %s", tok); 232 | if ((dash = strchr(tok, '-')) == nullptr) 233 | { 234 | unsigned int offset = RTC_SIZE; 235 | if (sscanf(tok, "%02X", &offset) != 1) 236 | break; 237 | if (offset >= RTC_SIZE) 238 | { 239 | DBGLOG("RTCFX", "rtc offset %02X is not valid", offset); 240 | break; 241 | } 242 | result = emulated_flag[offset] = true; 243 | DBGLOG("RTCFX", "rtc offset %02X is marked as emulated", offset); 244 | } 245 | else 246 | { 247 | unsigned int soffset = RTC_SIZE, eoffset = RTC_SIZE; 248 | char *rstart = tok, *rend = dash+1; 249 | *dash = '\0'; 250 | if (sscanf(rstart, "%02X", &soffset) == 1 && sscanf(rend, "%02X", &eoffset) == 1) 251 | { 252 | if (soffset >= RTC_SIZE) 253 | { 254 | DBGLOG("RTCFX", "rtc start offset %02X is not valid", soffset); 255 | break; 256 | } 257 | 258 | if (eoffset >= RTC_SIZE) 259 | { 260 | DBGLOG("RTCFX", "rtc end offset %02X is not valid", eoffset); 261 | break; 262 | } 263 | 264 | if (soffset >= eoffset) 265 | { 266 | DBGLOG("RTCFX", "rtc start offset %02X must be less than end offset %02X", soffset, eoffset); 267 | break; 268 | } 269 | 270 | for (unsigned int i = soffset; i <= eoffset; ++i) 271 | result = emulated_flag[i] = true; 272 | DBGLOG("RTCFX", "rtc range from offset %02X to offset %02X is marked as emulated", soffset, eoffset); 273 | } 274 | else 275 | { 276 | DBGLOG("RTCFX", "boot-arg rtcfx_exclude can't be parsed properly"); 277 | break; 278 | } 279 | } 280 | 281 | tok = end; 282 | } 283 | return result; 284 | } 285 | 286 | //============================================================================== 287 | 288 | void RTCMemoryFixup::hookProvider(IOService *provider) 289 | { 290 | if (orgIoRead8 == nullptr || orgIoWrite8 == nullptr) 291 | { 292 | bool suppress_errors = false; 293 | OSData* data = nullptr; 294 | static constexpr size_t rtcfx_exclude_size = 512; 295 | auto rtcfx_exclude_tmp = Buffer::create(rtcfx_exclude_size); 296 | if (rtcfx_exclude_tmp && PE_parse_boot_argn("rtcfx_exclude", rtcfx_exclude_tmp, rtcfx_exclude_size)) 297 | { 298 | DBGLOG("RTCFX", "boot-arg rtcfx_exclude specified, value = %s", rtcfx_exclude_tmp); 299 | suppress_errors = excludeAddresses(rtcfx_exclude_tmp); 300 | } 301 | else if (rtcfx_exclude_tmp && (data = OSDynamicCast(OSData, provider->getProperty("rtcfx_exclude"))) != nullptr) 302 | { 303 | if (data->getLength() < rtcfx_exclude_size) 304 | { 305 | lilu_os_strncpy(rtcfx_exclude_tmp, reinterpret_cast(data->getBytesNoCopy()), data->getLength()); 306 | DBGLOG("RTCFX", "property rtcfx_exclude specified, value = %s", rtcfx_exclude_tmp); 307 | suppress_errors = excludeAddresses(rtcfx_exclude_tmp); 308 | } 309 | else 310 | { 311 | SYSLOG("RTCFX", "RTCMemoryFixup::hookProvider: length of rtcfx_exclude cannot excceed 512 bytes"); 312 | } 313 | } 314 | 315 | readAndApplyRtcBlacklistFromNvram(suppress_errors); 316 | 317 | if (rtcfx_exclude_tmp) 318 | Buffer::deleter(rtcfx_exclude_tmp); 319 | } 320 | 321 | if (orgIoRead8 == nullptr) 322 | { 323 | if (KernelPatcher::routeVirtual(provider, IOPortAccessOffset::ioRead8, ioRead8, &orgIoRead8)) 324 | DBGLOG("RTCFX", "RTCMemoryFixup::hookProvider for ioRead8 was successful"); 325 | else 326 | SYSLOG("RTCFX", "RTCMemoryFixup::hookProvider for ioRead8 was failed"); 327 | } 328 | 329 | if (orgIoWrite8 == nullptr) 330 | { 331 | if (KernelPatcher::routeVirtual(provider, IOPortAccessOffset::ioWrite8, ioWrite8, &orgIoWrite8)) 332 | DBGLOG("RTCFX", "RTCMemoryFixup::hookProvider for ioWrite8 was successful"); 333 | else 334 | SYSLOG("RTCFX", "RTCMemoryFixup::hookProvider for ioWrite8 was failed"); 335 | } 336 | } 337 | 338 | //============================================================================== 339 | 340 | void RTCMemoryFixup::readAndApplyRtcBlacklistFromNvram(bool suppress_errors) { 341 | NVStorage storage; 342 | if (storage.init()) { 343 | uint32_t size = 0; 344 | auto buf = storage.read(OcRtcBlacklistKey, size, NVStorage::OptRaw); 345 | if (buf) { 346 | if (size > RTC_SIZE) 347 | size = RTC_SIZE; 348 | for (unsigned int i=0; i(size); 363 | if (buf) { 364 | uint32_t attr = 0; 365 | auto status = rt->getVariable(OcRtcBlacklistKeyEfi, &EfiRuntimeServices::LiluVendorGuid, &attr, &size, buf); 366 | if (status == EFI_SUCCESS) { 367 | if (size > RTC_SIZE) 368 | size = RTC_SIZE; 369 | for (unsigned int i=0; iput(); 380 | } else 381 | SYSLOG("RTCFX", "failed to load efi rt services for rtc-blacklist"); 382 | } 383 | } 384 | -------------------------------------------------------------------------------- /RTCMemoryFixup/RTCMemoryFixup.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // RTCMemoryFixup.hpp 3 | // RTCMemoryFixup 4 | // 5 | // Copyright © 2020 lvs1974. All rights reserved. 6 | // 7 | 8 | #ifndef RTCMemoryFixup_h 9 | #define RTCMemoryFixup_h 10 | 11 | #define CMOS_ADDREG1 0x70 12 | #define CMOS_DATAREG1 0x71 13 | #define CMOS_ADDREG2 0x72 14 | #define CMOS_DATAREG2 0x73 15 | 16 | class EXPORT RTCMemoryFixup : public IOService 17 | { 18 | OSDeclareDefaultStructors(RTCMemoryFixup); 19 | typedef IOService super; 20 | 21 | public: 22 | virtual bool init(OSDictionary *propTable) override; 23 | virtual bool attach(IOService *provider) override; 24 | virtual IOService* probe(IOService * provider, SInt32 *score) override; 25 | virtual bool start(IOService *provider) override; 26 | virtual void stop(IOService *provider) override; 27 | virtual void free() override; 28 | 29 | private: 30 | static bool excludeAddresses(char* rtcfx_exclude); 31 | static void hookProvider(IOService* provider); 32 | static void readAndApplyRtcBlacklistFromNvram(bool suppress_errors); 33 | 34 | using t_io_read8 = UInt8 (*)(IOService * that, UInt16 offset, IOMemoryMap * map); 35 | using t_io_write8 = void (*)(IOService * that, UInt16 offset, UInt8 value, IOMemoryMap * map); 36 | 37 | 38 | static UInt8 ioRead8(IOService * that, UInt16 offset, IOMemoryMap * map); 39 | static void ioWrite8(IOService * that, UInt16 offset, UInt8 value, IOMemoryMap * map); 40 | 41 | 42 | /** 43 | * Fixed offsets for I/O port access virtual methods 44 | */ 45 | struct IOPortAccessOffset { 46 | enum : size_t { 47 | ioRead8 = 0x978/8, 48 | ioWrite8 = 0x960/8, 49 | }; 50 | }; 51 | 52 | private: 53 | static IOService *service_provider; 54 | static t_io_read8 orgIoRead8; 55 | static t_io_write8 orgIoWrite8; 56 | 57 | static UInt16 cmd_reg; 58 | static UInt16 cmd_offset; 59 | 60 | enum { RTC_SIZE = 256 }; 61 | static UInt8 emulated_rtc_mem[RTC_SIZE]; 62 | static bool emulated_flag[RTC_SIZE]; 63 | }; 64 | 65 | 66 | #endif // RTCMemoryFixup_h 67 | --------------------------------------------------------------------------------