├── .gitignore ├── ACPI.cs ├── AMD_MMIO.cs ├── AOD.cs ├── AodData.cs ├── Constants.cs ├── Cpu.cs ├── CpuInitSettings.cs ├── DRAM ├── BaseDramTimings.cs ├── Capacity.cs ├── Ddr4Timings.cs ├── Ddr5Timings.cs ├── IDramTimings.cs ├── MemoryConfig.cs └── MemoryModule.cs ├── Dictionaries ├── AodDictionaries.cs ├── DDR4Dictionary.cs └── DDR5Dictionary.cs ├── External ├── InpOut │ ├── DLPortIO.txt │ ├── ReadMe.txt │ ├── Win32 │ │ ├── InstallDriver.exe │ │ ├── inpout32.dll │ │ ├── inpout32.h │ │ └── inpout32.lib │ └── license.txt ├── WinIo │ ├── LICENSE.txt │ ├── WinIo32.dll │ └── WinIo32.sys └── WinRing0 │ ├── LICENSE.txt │ ├── WinRing0.sys │ └── WinRing0x64.sys ├── IOModule.cs ├── LICENSE ├── Mailbox ├── HSMPMailbox.cs ├── MP1Mailbox.cs ├── Mailbox.cs └── RSMUMailbox.cs ├── OHWM ├── FirmwareTable.cs ├── GroupAffinity.cs ├── IOControlCode.cs ├── InteropMethods.cs ├── KernelDriver.cs ├── Opcode.cs ├── OperatingSystem.cs ├── Ring0.cs └── ThreadAffinity.cs ├── PowerTable.cs ├── Properties └── AssemblyInfo.cs ├── README.md ├── SMU.cs ├── SMUCommands ├── BaseSMUCommand.cs ├── CmdResult.cs ├── GetBoostLimitFrequency.cs ├── GetCorePerformanceData.cs ├── GetDramAddress.cs ├── GetIsOverclockable.cs ├── GetLN2Mode.cs ├── GetPBOScalar.cs ├── GetPsmMarginSingleCore.cs ├── GetSmuVersion.cs ├── GetTableVersion.cs ├── SendTestMessage.cs ├── SetBoostLimitAllCore.cs ├── SetFrequencyAllCore.cs ├── SetFrequencySingleCore.cs ├── SetOcMode.cs ├── SetOverclockCpuVid.cs ├── SetPBOScalar.cs ├── SetPsmMarginAllCores.cs ├── SetPsmMarginSingleCore.cs ├── SetSmuLimit.cs ├── SetToolsDramAddress.cs └── TransferTableToDram.cs ├── SystemInfo.cs ├── Utils.cs ├── WMI.cs ├── WinRing0.sys ├── WinRing0x64.sys ├── ZenStates-Core.csproj └── ZenStates-Core.sln /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | [Aa][Rr][Mm]/ 24 | [Aa][Rr][Mm]64/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015/2017 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # Visual Studio 2017 auto generated files 36 | Generated\ Files/ 37 | 38 | # MSTest test Results 39 | [Tt]est[Rr]esult*/ 40 | [Bb]uild[Ll]og.* 41 | 42 | # NUNIT 43 | *.VisualState.xml 44 | TestResult.xml 45 | 46 | # Build Results of an ATL Project 47 | [Dd]ebugPS/ 48 | [Rr]eleasePS/ 49 | dlldata.c 50 | 51 | # Benchmark Results 52 | BenchmarkDotNet.Artifacts/ 53 | 54 | # .NET Core 55 | project.lock.json 56 | project.fragment.lock.json 57 | artifacts/ 58 | 59 | # StyleCop 60 | StyleCopReport.xml 61 | 62 | # Files built by Visual Studio 63 | *_i.c 64 | *_p.c 65 | *_h.h 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.iobj 70 | *.pch 71 | *.pdb 72 | *.ipdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *_wpftmp.csproj 83 | *.log 84 | *.vspscc 85 | *.vssscc 86 | .builds 87 | *.pidb 88 | *.svclog 89 | *.scc 90 | 91 | # Chutzpah Test files 92 | _Chutzpah* 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opendb 99 | *.opensdf 100 | *.sdf 101 | *.cachefile 102 | *.VC.db 103 | *.VC.VC.opendb 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | *.sap 110 | 111 | # Visual Studio Trace Files 112 | *.e2e 113 | 114 | # TFS 2012 Local Workspace 115 | $tf/ 116 | 117 | # Guidance Automation Toolkit 118 | *.gpState 119 | 120 | # ReSharper is a .NET coding add-in 121 | _ReSharper*/ 122 | *.[Rr]e[Ss]harper 123 | *.DotSettings.user 124 | 125 | # JustCode is a .NET coding add-in 126 | .JustCode 127 | 128 | # TeamCity is a build add-in 129 | _TeamCity* 130 | 131 | # DotCover is a Code Coverage Tool 132 | *.dotCover 133 | 134 | # AxoCover is a Code Coverage Tool 135 | .axoCover/* 136 | !.axoCover/settings.json 137 | 138 | # Visual Studio code coverage results 139 | *.coverage 140 | *.coveragexml 141 | 142 | # NCrunch 143 | _NCrunch_* 144 | .*crunch*.local.xml 145 | nCrunchTemp_* 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # Note: Comment the next line if you want to checkin your web deploy settings, 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 179 | # checkin your Azure Web App publish settings, but sensitive information contained 180 | # in these scripts will be unencrypted 181 | PublishScripts/ 182 | 183 | # NuGet Packages 184 | *.nupkg 185 | # The packages folder can be ignored because of Package Restore 186 | **/[Pp]ackages/* 187 | # except build/, which is used as an MSBuild target. 188 | !**/[Pp]ackages/build/ 189 | # Uncomment if necessary however generally it will be regenerated when needed 190 | #!**/[Pp]ackages/repositories.config 191 | # NuGet v3's project.json files produces more ignorable files 192 | *.nuget.props 193 | *.nuget.targets 194 | 195 | # Microsoft Azure Build Output 196 | csx/ 197 | *.build.csdef 198 | 199 | # Microsoft Azure Emulator 200 | ecf/ 201 | rcf/ 202 | 203 | # Windows Store app package directories and files 204 | AppPackages/ 205 | BundleArtifacts/ 206 | Package.StoreAssociation.xml 207 | _pkginfo.txt 208 | *.appx 209 | 210 | # Visual Studio cache files 211 | # files ending in .cache can be ignored 212 | *.[Cc]ache 213 | # but keep track of directories ending in .cache 214 | !?*.[Cc]ache/ 215 | 216 | # Others 217 | ClientBin/ 218 | ~$* 219 | *~ 220 | *.dbmdl 221 | *.dbproj.schemaview 222 | *.jfm 223 | *.pfx 224 | *.publishsettings 225 | orleans.codegen.cs 226 | 227 | # Including strong name files can present a security risk 228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 229 | #*.snk 230 | 231 | # Since there are multiple workflows, uncomment next line to ignore bower_components 232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 233 | #bower_components/ 234 | 235 | # RIA/Silverlight projects 236 | Generated_Code/ 237 | 238 | # Backup & report files from converting an old project file 239 | # to a newer Visual Studio version. Backup files are not needed, 240 | # because we have git ;-) 241 | _UpgradeReport_Files/ 242 | Backup*/ 243 | UpgradeLog*.XML 244 | UpgradeLog*.htm 245 | ServiceFabricBackup/ 246 | *.rptproj.bak 247 | 248 | # SQL Server files 249 | *.mdf 250 | *.ldf 251 | *.ndf 252 | 253 | # Business Intelligence projects 254 | *.rdl.data 255 | *.bim.layout 256 | *.bim_*.settings 257 | *.rptproj.rsuser 258 | *- Backup*.rdl 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush personal settings 299 | .cr/personal 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | 336 | # Local History for Visual Studio 337 | .localhistory/ 338 | 339 | # BeatPulse healthcheck temp database 340 | healthchecksdb 341 | *.bak 342 | -------------------------------------------------------------------------------- /ACPI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace ZenStates.Core 5 | { 6 | public class ACPI 7 | { 8 | public static class TableSignature 9 | { 10 | public const string RSDP = "RSD PTR "; 11 | public const string RSDT = "RSDT"; 12 | public const string XSDT = "XSDT"; 13 | public const string SSDT = "SSDT"; 14 | // Table OemId signatures 15 | public const string AOD_ = "AOD "; 16 | public const string AAOD = "AMD AOD"; 17 | public const string LENOVO_AOD = "CB-01 "; 18 | // Region signatures 19 | public const string AODE = "AODE"; 20 | public const string AODT = "AODT"; 21 | } 22 | 23 | internal const ushort EBDA_START_SEGMENT_PTR = 0x40e; 24 | internal const uint EBDA_EARLIEST_START = 0x80000; 25 | internal const uint EBDA_END = 0x9ffff; 26 | internal const uint RSDP_REGION_BASE_ADDRESS = 0x0e0000; 27 | internal const int RSDP_REGION_LENGTH = 0x01ffff; 28 | 29 | // 5.2.5.3 RSDP Structure 30 | // https://uefi.org/sites/default/files/resources/ACPI_5_1_Errata_B.PDF p.110 31 | [Serializable] 32 | [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 36)] 33 | public struct RSDP 34 | { 35 | // [FieldOffset(0)] 36 | public ulong Signature; // "RSD PTR " (note the space at the end) 37 | // [FieldOffset(8)] 38 | public byte Checksum; // Includes only the first 20 bytes of this table, bytes 0 to 19, including the checksum field. These bytes must sum to zero. 39 | // [FieldOffset(9)] 40 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] 41 | public byte[] OEMID; 42 | // [FieldOffset(15)] 43 | public byte Revision; 44 | // [FieldOffset(16)] 45 | public uint RsdtAddress; // 32 bit physical address of the RSDT table 46 | // [FieldOffset(20)] 47 | public uint Length; // The length of the whole table, in bytes, including the header, starting from offset 0. 48 | // [FieldOffset(24)] 49 | public ulong XsdtAddress; // 64 bit physical address of the XSDT table 50 | // [FieldOffset(32)] 51 | public byte ExtendedChecksum; // This is a checksum of the entire table, including both checksum fields 52 | // [FieldOffset(33)] 53 | public byte Reserved1; 54 | // [FieldOffset(34)] 55 | public byte Reserved2; 56 | // [FieldOffset(35)] 57 | public byte Reserved3; 58 | }; 59 | 60 | [Serializable] 61 | [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 36)] 62 | public struct SDTHeader 63 | { 64 | // [FieldOffset(0)] 65 | public uint Signature; 66 | // [FieldOffset(4)] 67 | public uint Length; 68 | // [FieldOffset(8)] 69 | public byte Revision; 70 | // [FieldOffset(9)] 71 | public byte Checksum; 72 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] 73 | // [FieldOffset(10)] 74 | public byte[] OEMID; 75 | // [FieldOffset(16)] 76 | public ulong OEMTableID; 77 | // [FieldOffset(24)] 78 | public uint OEMRevision; 79 | // [FieldOffset(28)] 80 | public uint CreatorID; 81 | // [FieldOffset(32)] 82 | public uint CreatorRevision; 83 | }; 84 | 85 | [Serializable] 86 | [StructLayout(LayoutKind.Sequential)] 87 | public struct ParsedSDTHeader 88 | { 89 | public string Signature; 90 | public uint Length; 91 | public byte Revision; 92 | public byte Checksum; 93 | public string OEMID; 94 | public string OEMTableID; 95 | public uint OEMRevision; 96 | public string CreatorID; 97 | public uint CreatorRevision; 98 | }; 99 | 100 | [Serializable] 101 | [StructLayout(LayoutKind.Sequential)] 102 | public struct ACPITable 103 | { 104 | public SDTHeader RawHeader; 105 | public ParsedSDTHeader Header; 106 | [MarshalAs(UnmanagedType.ByValArray)] 107 | public byte[] Data; 108 | }; 109 | 110 | [Serializable] 111 | [StructLayout(LayoutKind.Sequential)] 112 | public struct RSDT 113 | { 114 | public SDTHeader Header; 115 | [MarshalAs(UnmanagedType.ByValArray)] 116 | public uint[] Data; 117 | }; 118 | 119 | // 5.2.9 Fixed ACPI Description Table (FADT) 120 | // https://uefi.org/sites/default/files/resources/ACPI_5_1_Errata_B.PDF p.116 121 | [Serializable] 122 | [StructLayout(LayoutKind.Explicit, Pack = 1)] 123 | public struct FADT 124 | { 125 | [FieldOffset(0)] 126 | public SDTHeader Header; 127 | [FieldOffset(36)] 128 | public uint FIRMWARE_CTRL; // Physical memory address of the FACS table 129 | [FieldOffset(40)] 130 | public uint DSDT; // Physical memory address of the DSDT table 131 | [FieldOffset(132)] 132 | public ulong X_FIRMWARE_CTRL; 133 | [FieldOffset(140)] 134 | public ulong X_DSDT; 135 | } 136 | 137 | // https://github.com/rust-osdev/acpi/blob/main/acpi/src/address.rs 138 | public enum AddressSpace : byte 139 | { 140 | SystemMemory, 141 | SystemIo, 142 | PciConfigSpace, 143 | EmbeddedController, 144 | SMBus, 145 | SystemCmos, 146 | PciBarTarget, 147 | Ipmi, 148 | GeneralIo, 149 | GenericSerialBus, 150 | PlatformCommunicationsChannel, 151 | FunctionalFixedHardware, 152 | OemDefined, 153 | } 154 | 155 | [Serializable] 156 | [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 16)] 157 | public struct OperationRegion 158 | { 159 | public uint RegionName; 160 | public AddressSpace RegionSpace; 161 | public byte _unknown1; 162 | public uint Offset; 163 | public byte _unknown2; 164 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] 165 | public byte[] Length; 166 | public byte _unknown3; 167 | public byte _unknown4; 168 | public byte _unknown5; 169 | }; 170 | 171 | private readonly IOModule io; 172 | 173 | public ACPI(IOModule io) 174 | { 175 | this.io = io ?? throw new ArgumentNullException(nameof(io)); 176 | } 177 | 178 | public static ParsedSDTHeader ParseRawHeader(SDTHeader rawHeader) 179 | { 180 | return new ParsedSDTHeader() 181 | { 182 | Signature = Utils.GetStringFromBytes(rawHeader.Signature), 183 | Length = rawHeader.Length, 184 | Revision = rawHeader.Revision, 185 | Checksum = rawHeader.Checksum, 186 | OEMID = Utils.GetStringFromBytes(rawHeader.OEMID), 187 | OEMTableID = Utils.GetStringFromBytes(rawHeader.OEMTableID), 188 | OEMRevision = rawHeader.OEMRevision, 189 | CreatorID = Utils.GetStringFromBytes(rawHeader.CreatorID), 190 | CreatorRevision = rawHeader.CreatorRevision, 191 | }; 192 | } 193 | 194 | // ASCII string to Little-Endian uint, used for table signatures and OEM ID 195 | public static uint Signature(string ascii) 196 | { 197 | uint val = 0x0; 198 | int length = Math.Min(ascii.Length, 4); 199 | 200 | for (int i = 0; i < length; i++) 201 | { 202 | val |= (uint)ascii[i] << i * 8; 203 | } 204 | return val; 205 | } 206 | 207 | public static ulong SignatureUL(string ascii) 208 | { 209 | ulong val = 0x0; 210 | int length = Math.Min(ascii.Length, 8); 211 | 212 | for (int i = 0; i < length; i++) 213 | { 214 | val |= (ulong)ascii[i] << i * 8; 215 | } 216 | return val; 217 | } 218 | 219 | public static byte[] ByteSignature(string ascii) => BitConverter.GetBytes(Signature(ascii)); 220 | public static byte[] ByteSignatureUL(string ascii) => BitConverter.GetBytes(SignatureUL(ascii)); 221 | 222 | public T GetHeader(uint address, int length = 36) where T : new() 223 | { 224 | byte[] bytes = io.ReadMemory(new IntPtr(address), length); 225 | return Utils.ByteArrayToStructure(bytes); 226 | } 227 | 228 | public T GetHeader(ulong address, int length = 36) where T : new() 229 | { 230 | byte[] bytes = io.ReadMemory(new IntPtr((long)address), length); 231 | return Utils.ByteArrayToStructure(bytes); 232 | } 233 | 234 | public RSDP GetRsdp() 235 | { 236 | byte[] bytes = io.ReadMemory(new IntPtr(RSDP_REGION_BASE_ADDRESS), RSDP_REGION_LENGTH); 237 | int rsdpOffset = Utils.FindSequence(bytes, 0, ByteSignatureUL(TableSignature.RSDP)); 238 | 239 | if (rsdpOffset < 0) 240 | throw new SystemException("ACPI: Could not find RSDP signature"); 241 | 242 | return Utils.ByteArrayToStructure(io.ReadMemory(new IntPtr(RSDP_REGION_BASE_ADDRESS + rsdpOffset), 36)); 243 | } 244 | 245 | public RSDT GetRsdt() 246 | { 247 | RSDT rsdtTable; 248 | RSDP rsdp = GetRsdp(); 249 | SDTHeader rsdtHeader = GetHeader(rsdp.RsdtAddress > 0 ? rsdp.RsdtAddress : rsdp.XsdtAddress); 250 | byte[] rawTable = io.ReadMemory(new IntPtr(rsdp.RsdtAddress > 0 ? rsdp.RsdtAddress : (long)rsdp.XsdtAddress), (int)rsdtHeader.Length); 251 | 252 | if (rawTable == null) 253 | return new RSDT(); 254 | 255 | GCHandle handle = GCHandle.Alloc(rawTable, GCHandleType.Pinned); 256 | try 257 | { 258 | int headerSize = Marshal.SizeOf(rsdtHeader); 259 | int dataSize = (int)rsdtHeader.Length - headerSize; 260 | rsdtTable = new RSDT() 261 | { 262 | Header = rsdtHeader, 263 | Data = new uint[dataSize], 264 | }; 265 | Buffer.BlockCopy(rawTable, headerSize, rsdtTable.Data, 0, dataSize); 266 | } 267 | finally 268 | { 269 | handle.Free(); 270 | } 271 | return rsdtTable; 272 | } 273 | 274 | public static ACPITable ParseSdtTable(byte[] rawTable) 275 | { 276 | ACPITable acpiTable; 277 | GCHandle handle = GCHandle.Alloc(rawTable, GCHandleType.Pinned); 278 | try 279 | { 280 | SDTHeader rawHeader = (SDTHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(SDTHeader)); 281 | int headerSize = Marshal.SizeOf(rawHeader); 282 | int dataSize = (int)rawHeader.Length - headerSize; 283 | acpiTable = new ACPITable() 284 | { 285 | RawHeader = rawHeader, 286 | Header = ParseRawHeader(rawHeader), 287 | Data = new byte[dataSize], 288 | }; 289 | Buffer.BlockCopy(rawTable, headerSize, acpiTable.Data, 0, dataSize); 290 | } 291 | finally 292 | { 293 | handle.Free(); 294 | } 295 | return acpiTable; 296 | } 297 | 298 | private static T ReadMemory(IntPtr address) 299 | { 300 | T result = default; 301 | Marshal.PtrToStructure(address, result); 302 | return result; 303 | } 304 | } 305 | } 306 | -------------------------------------------------------------------------------- /AMD_MMIO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ZenStates.Core 4 | { 5 | public class AMD_MMIO 6 | { 7 | // https://www.amd.com/system/files/TechDocs/52740_16h_Models_30h-3Fh_BKDG.pdf (page 859) 8 | internal const uint AMD_MMIO_BASE_ADDRESS = 0xFED80000; 9 | internal const uint MISC_BASE_ADDRESS = AMD_MMIO_BASE_ADDRESS + 0xE00; 10 | internal const uint SMBUS_BASE_ADDRESS = AMD_MMIO_BASE_ADDRESS + 0xA00; 11 | internal const uint SMUIO_BASE_ADDRESS = 0x0005A000; 12 | // internal const uint IOMUX_BASE = AMD_MMIO_BASE_ADDRESS + 0xD00; 13 | internal const uint MISC_GPPClkCntrl = MISC_BASE_ADDRESS + 0; 14 | internal const uint MISC_ClkOutputCntrl = MISC_BASE_ADDRESS + 0x04; 15 | internal const uint MISC_CGPLLConfig1 = MISC_BASE_ADDRESS + 0x08; 16 | internal const uint MISC_CGPLLConfig2 = MISC_BASE_ADDRESS + 0x0C; 17 | internal const uint MISC_CGPLLConfig3 = MISC_BASE_ADDRESS + 0x10; 18 | internal const uint MISC_CGPLLConfig4 = MISC_BASE_ADDRESS + 0x14; 19 | internal const uint MISC_CGPLLConfig5 = MISC_BASE_ADDRESS + 0x18; 20 | internal const uint MISC_ClkCntl1 = MISC_BASE_ADDRESS + 0x40; 21 | internal const uint MISC_StrapStatus = MISC_BASE_ADDRESS + 0x80; 22 | internal const uint SMBUS_BASE_ADDRESS_REG = 0x300; 23 | // internal const uint IOMUX_LPCCLK1 = IOMUX_BASE + 0x1F; 24 | 25 | private readonly IOModule io; 26 | 27 | public enum ClkGen : int 28 | { 29 | ERROR = -1, 30 | EXTERNAL = 0, 31 | INTERNAL = 1, 32 | } 33 | 34 | public AMD_MMIO(IOModule io) 35 | { 36 | this.io = io; 37 | } 38 | 39 | private static int CalculateBclkIndex(int bclk) 40 | { 41 | if (bclk > 151) 42 | bclk = 151; 43 | else if (bclk < 96) 44 | bclk = 96; 45 | 46 | if ((bclk & 128) != 0) 47 | return bclk ^ 164; 48 | return bclk ^ 100; 49 | } 50 | 51 | private uint GetSmbusBaseAddress() 52 | { 53 | io.GetPhysLong(new UIntPtr(SMBUS_BASE_ADDRESS_REG), out uint data); 54 | if (data != 0) 55 | { 56 | uint value = (data >> 8) & 0x7F; 57 | return value << 8; 58 | } 59 | return 0; 60 | } 61 | 62 | private static int CalculateBclkFromIndex(int index) 63 | { 64 | if (index < 32) 65 | return index ^ 100; 66 | return index ^ 164; 67 | } 68 | 69 | /** 70 | * [17] ClkGenStrap 71 | * 1=Internal clocking mode; Use 48MHz crystal 72 | * clock as the reference clock. 0=External clocking mode; Use 100MHz differential spread clock as the 73 | * reference clock 74 | * [12] CPUClkSelStrap 75 | */ 76 | public ClkGen GetStrapStatus() 77 | { 78 | if (io.GetPhysLong((UIntPtr)MISC_StrapStatus, out uint value)) 79 | return (ClkGen)Utils.GetBits(value, 17, 1); 80 | return ClkGen.ERROR; 81 | } 82 | 83 | private bool DisableSpreadSpectrum() 84 | { 85 | if (io.GetPhysLong((UIntPtr)MISC_CGPLLConfig1, out uint value)) 86 | return io.SetPhysLong((UIntPtr)MISC_CGPLLConfig1, Utils.SetBits(value, 0, 0, 0)); 87 | return false; 88 | } 89 | 90 | private bool CG1AtomicUpdate() 91 | { 92 | if (io.GetPhysLong((UIntPtr)MISC_ClkCntl1, out uint value)) 93 | return io.SetPhysLong((UIntPtr)MISC_ClkCntl1, Utils.SetBits(value, 30, 1, 1)); 94 | return false; 95 | } 96 | 97 | /** 98 | * [11] GPP_CLK3_ClockOutputOverride. Read-write. Reset: 0. GPP_CLK3 clock output override control. GPP_CLK3 is a bi-directional pin depending on LPCCLK1 strap value. If Strap 99 | * (LPCCLK1)==1, GPP_CLK3 provides clock for external device and output buffer will be on. If Strap 100 | * (LPCCLK1)==0, GPP_CLK3 receives clock from external clock chip and output buffer will be off. 101 | * This override bit allows to invert the strap that controls GPP_CLK3 clock output buffer. 0=Use the 102 | * strap value (LPCCLK1) to determine whether GPP_CLK3 clock output buffer is on or off. 1=Invert 103 | * the strap that controls GPP_CLK3 clock output buffer 104 | * 105 | * [10] CPU_CLK_ClockSourceOverride. Read-write. Reset: 0. CPU_CLK clock source override control. 106 | * CPU_CLK clock source is controlled by strap (LPCCLK1). If Strap (LPCCLK1)==1, CPU_CLK 107 | * clock source is from CG_PLL. If Strap (LPCCLK1)==0, CPU_CLK clock source is from external 108 | * clock chip through GPP_CLK3_P/N pins. This override bit allows to invert the strap that controls 109 | * CPU_CLK clock source. 0=Use the strap value (LPCCLK1) to determine whether CPU_CLK clock 110 | * source from either CG_PLL or external clock chip. 1=Invert the strap that controls CPU_CLK clock 111 | * source. 112 | */ 113 | public bool SetBclk(double bclk) 114 | { 115 | DisableSpreadSpectrum(); 116 | 117 | // CCG1PLL_FBDIV_Enable, bit 25 118 | bool res = io.GetPhysLong((UIntPtr)MISC_ClkCntl1, out uint value); 119 | res = io.SetPhysLong((UIntPtr)MISC_ClkCntl1, Utils.SetBits(value, 25, 1, 1)); 120 | 121 | if (res) 122 | { 123 | int index = CalculateBclkIndex((int)bclk); 124 | uint fraction = (uint)((bclk - (int)bclk) / 0.0625); 125 | 126 | if (fraction > 15) 127 | fraction = 15; 128 | 129 | res = io.GetPhysLong((UIntPtr)MISC_CGPLLConfig3, out value); 130 | value = Utils.SetBits(value, 4, 9, (uint)index); 131 | value = Utils.SetBits(value, 25, 4, fraction); 132 | if (io.SetPhysLong((UIntPtr)MISC_CGPLLConfig3, value)) 133 | return CG1AtomicUpdate(); 134 | } 135 | 136 | return res; 137 | } 138 | 139 | public double? GetBclk() 140 | { 141 | if (io.GetPhysLong((UIntPtr)MISC_CGPLLConfig3, out uint value)) 142 | { 143 | uint index = Utils.GetBits(value, 4, 9); 144 | uint fMul = Utils.GetBits(value, 25, 4); 145 | return CalculateBclkFromIndex((int)index) + fMul * 0.0625f; 146 | } 147 | return null; 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /AodData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using static ZenStates.Core.AOD; 5 | 6 | namespace ZenStates.Core 7 | { 8 | // [Serializable] 9 | public class AodData 10 | { 11 | public int SMTEn { get; set; } 12 | public int MemClk { get; set; } 13 | public int Tcl { get; set; } 14 | public int Trcd { get; set; } 15 | public int TrcdWr { get; set; } 16 | public int TrcdRd { get; set; } 17 | public int Trp { get; set; } 18 | public int Tras { get; set; } 19 | public int Trc { get; set; } 20 | public int Twr { get; set; } 21 | public int Trfc { get; set; } 22 | public int Trfc2 { get; set; } 23 | public int Trfcsb { get; set; } 24 | public int Trtp { get; set; } 25 | public int TrrdL { get; set; } 26 | public int TrrdS { get; set; } 27 | public int Tfaw { get; set; } 28 | public int TwtrL { get; set; } 29 | public int TwtrS { get; set; } 30 | public int TrdrdScL { get; set; } 31 | public int TrdrdSc { get; set; } 32 | public int TrdrdSd { get; set; } 33 | public int TrdrdDd { get; set; } 34 | public int TwrwrScL { get; set; } 35 | public int TwrwrSc { get; set; } 36 | public int TwrwrSd { get; set; } 37 | public int TwrwrDd { get; set; } 38 | public int Twrrd { get; set; } 39 | public int Trdwr { get; set; } 40 | public CadBusDrvStren CadBusDrvStren { get; set; } 41 | public ProcDataDrvStren ProcDataDrvStren { get; set; } 42 | public ProcOdt ProcOdt { get; set; } 43 | public ProcOdt ProcOdtPullUp { get; set; } 44 | public ProcOdt ProcOdtPullDown { get; set; } 45 | public ProcOdtImpedance ProcCaOdt { get; set; } 46 | public ProcOdtImpedance ProcCkOdt { get; set; } 47 | public ProcOdtImpedance ProcDqOdt { get; set; } 48 | public ProcOdtImpedance ProcDqsOdt { get; set; } 49 | public DramDataDrvStren DramDataDrvStren { get; set; } 50 | public Rtt RttNomWr { get; set; } 51 | public Rtt RttNomRd { get; set; } 52 | public Rtt RttWr { get; set; } 53 | public Rtt RttPark { get; set; } 54 | public Rtt RttParkDqs { get; set; } 55 | public Voltage MemVddio { get; set; } 56 | public Voltage MemVddq { get; set; } 57 | public Voltage MemVpp { get; set; } 58 | public Voltage ApuVddio { get; set; } 59 | 60 | public static AodData CreateFromByteArray(byte[] byteArray, Dictionary fieldDictionary) 61 | { 62 | AodData data = new AodData(); 63 | 64 | if (byteArray == null) return data; 65 | 66 | foreach (var entry in fieldDictionary) 67 | { 68 | try 69 | { 70 | string fieldName = entry.Key; 71 | int fieldOffset = entry.Value; 72 | 73 | PropertyInfo property = typeof(AodData).GetProperty(fieldName); 74 | if (fieldOffset > -1 && fieldOffset <= byteArray.Length - sizeof(int) && property != null) 75 | { 76 | Type propertyType = property.PropertyType; 77 | object fieldValue; 78 | 79 | if (propertyType.IsClass && propertyType != typeof(string)) 80 | { 81 | fieldValue = Activator.CreateInstance(propertyType, BitConverter.ToInt32(byteArray, fieldOffset)); 82 | } 83 | else 84 | { 85 | fieldValue = Convert.ChangeType(BitConverter.ToInt32(byteArray, fieldOffset), propertyType); 86 | } 87 | 88 | property.SetValue(data, fieldValue, null); 89 | } 90 | } 91 | catch (Exception e) 92 | { 93 | Console.WriteLine(e.ToString(), e.Message); 94 | } 95 | } 96 | 97 | return data; 98 | } 99 | 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Constants.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core 2 | { 3 | internal static class Constants 4 | { 5 | internal const string VENDOR_AMD = "AuthenticAMD"; 6 | internal const string VENDOR_HYGON = "HygonGenuine"; 7 | internal const uint F17H_M01H_SVI = 0x0005A000; 8 | internal const uint F17H_M60H_SVI = 0x0006F000; // Renoir only? 9 | internal const uint F17H_M01H_SVI_TEL_PLANE0 = (F17H_M01H_SVI + 0xC); 10 | internal const uint F17H_M01H_SVI_TEL_PLANE1 = (F17H_M01H_SVI + 0x10); 11 | internal const uint F17H_M30H_SVI_TEL_PLANE0 = (F17H_M01H_SVI + 0x14); 12 | internal const uint F17H_M30H_SVI_TEL_PLANE1 = (F17H_M01H_SVI + 0x10); 13 | internal const uint F17H_M60H_SVI_TEL_PLANE0 = (F17H_M60H_SVI + 0x38); 14 | internal const uint F17H_M60H_SVI_TEL_PLANE1 = (F17H_M60H_SVI + 0x3C); 15 | internal const uint F17H_M70H_SVI_TEL_PLANE0 = (F17H_M01H_SVI + 0x10); 16 | internal const uint F17H_M70H_SVI_TEL_PLANE1 = (F17H_M01H_SVI + 0xC); 17 | internal const uint F19H_M01H_SVI_TEL_PLANE0 = (F17H_M01H_SVI + 0x10); 18 | internal const uint F19H_M01H_SVI_TEL_PLANE1 = (F17H_M01H_SVI + 0x14); 19 | internal const uint F19H_M21H_SVI_TEL_PLANE0 = (F17H_M01H_SVI + 0x10); 20 | internal const uint F19H_M21H_SVI_TEL_PLANE1 = (F17H_M01H_SVI + 0xC); 21 | internal const uint F17H_CCD_TEMP = 0x00059954; 22 | internal const uint F19H_CCD_TEMP = 0x00059B08; 23 | internal const uint THM_CUR_TEMP = 0x00059800; 24 | internal const uint THM_CUR_TEMP_RANGE_SEL_MASK = 0x80000; 25 | internal const uint DEFAULT_MAILBOX_ARGS = 6; 26 | internal const uint HSMP_MAILBOX_ARGS = 8; 27 | internal const float PBO_SCALAR_MIN = 0.0f; 28 | internal const float PBO_SCALAR_MAX = 10.0f; 29 | internal const float PBO_SCALAR_DEFAULT = 1.0f; 30 | internal static readonly string[] MISIDENTIFIED_DALI_APU = { 31 | "Athlon Silver 3050GE", 32 | "Athlon Silver 3050U", 33 | "3015e", 34 | "3020e", 35 | "Athlon Gold 3150U", 36 | "Athlon Silver 3050e", 37 | "Ryzen 3 3250U", 38 | "Athlon 3000G", 39 | "Athlon 300GE", 40 | "Athlon 300U", 41 | "Athlon 320GE", 42 | "Ryzen 3 3200U", 43 | }; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /CpuInitSettings.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core 2 | { 3 | public class CpuInitSettings 4 | { 5 | public const int DefaultAutorefreshIntervalMs = 1000; 6 | 7 | public static readonly CpuInitSettings defaultSetttings = new CpuInitSettings(); 8 | public struct CpuInitModuleSettings 9 | { 10 | public bool? Enabled { get; set; } 11 | public bool? Autorefresh { get; set; } 12 | public int? AutorefreshInterval { get; set; } 13 | } 14 | 15 | public CpuInitModuleSettings IoModule { get; set; } 16 | public CpuInitModuleSettings Timings { get; set; } 17 | public CpuInitModuleSettings Aod { get; set; } 18 | public CpuInitModuleSettings Wmi { get; set; } 19 | public CpuInitModuleSettings Sensors { get; set; } 20 | 21 | public CpuInitSettings() 22 | { 23 | IoModule = new CpuInitModuleSettings() 24 | { 25 | Enabled = true 26 | }; 27 | Timings = new CpuInitModuleSettings() 28 | { 29 | Enabled = true, 30 | Autorefresh = true, 31 | AutorefreshInterval = DefaultAutorefreshIntervalMs 32 | }; 33 | Aod = new CpuInitModuleSettings() 34 | { 35 | Enabled = true 36 | }; 37 | Wmi = new CpuInitModuleSettings() 38 | { 39 | Enabled = true 40 | }; 41 | Sensors = new CpuInitModuleSettings() 42 | { 43 | Enabled = true, 44 | Autorefresh = true, 45 | AutorefreshInterval = DefaultAutorefreshIntervalMs 46 | }; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /DRAM/BaseDramTimings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using static ZenStates.Core.DRAM.MemoryConfig; 5 | 6 | namespace ZenStates.Core.DRAM 7 | { 8 | [Serializable] 9 | public abstract class BaseDramTimings : IDramTimings, IDisposable 10 | { 11 | private bool disposedValue; 12 | 13 | internal readonly Cpu cpu; 14 | internal Dictionary Dict { get; set; } 15 | 16 | public BaseDramTimings(Cpu cpuInstance) 17 | { 18 | cpu = cpuInstance; 19 | } 20 | 21 | public object this[string propertyName] 22 | { 23 | get 24 | { 25 | try 26 | { 27 | if (!string.IsNullOrEmpty(propertyName)) 28 | { 29 | PropertyInfo propertyInfo = GetPropertyInfo(propertyName); 30 | return propertyInfo?.GetValue(this, null); 31 | } 32 | return null; 33 | } 34 | catch 35 | { 36 | return null; 37 | } 38 | } 39 | set 40 | { 41 | try 42 | { 43 | if (!string.IsNullOrEmpty(propertyName)) 44 | { 45 | PropertyInfo propertyInfo = GetPropertyInfo(propertyName); 46 | propertyInfo?.SetValue(this, value, null); 47 | } 48 | } 49 | catch 50 | { 51 | // do nothing 52 | } 53 | } 54 | } 55 | 56 | private PropertyInfo GetPropertyInfo(string propertyName) 57 | { 58 | return GetType().GetProperty(propertyName); 59 | } 60 | 61 | public virtual void ReadBankGroupSwap(uint offset = 0) 62 | { 63 | uint bgsa0 = cpu.ReadDword(offset | 0x500D0); 64 | uint bgsa1 = cpu.ReadDword(offset | 0x500D4); 65 | uint bgs0 = cpu.ReadDword(offset | 0x50050); 66 | uint bgs1 = cpu.ReadDword(offset | 0x50058); 67 | 68 | BGS = (bgs0 == 0x87654321 && bgs1 == 0x87654321) ? 0 : 1U; 69 | BGSAlt = (Utils.GetBits(bgsa0, 4, 7) > 0 || Utils.GetBits(bgsa1, 4, 7) > 0) ? 1U : 0; 70 | } 71 | 72 | public virtual void Read(uint offset = 0) 73 | { 74 | ReadBankGroupSwap(offset); 75 | 76 | foreach (KeyValuePair entry in Dict) 77 | { 78 | foreach (TimingDef def in entry.Value) 79 | { 80 | if (this[def.Name] != null) 81 | { 82 | uint data = cpu.ReadDword(offset | entry.Key); 83 | this[def.Name] = Utils.BitSlice(data, def.HiBit, def.LoBit); 84 | } 85 | } 86 | } 87 | } 88 | 89 | public MemType Type { get; set; } 90 | public float Frequency => Ratio * 200; 91 | public float Ratio { get; internal set; } 92 | // public string TotalCapacity { get; internal set; } 93 | public uint BGS { get; internal set; } 94 | public uint BGSAlt { get; internal set; } 95 | public uint GDM { get; internal set; } 96 | public uint PowerDown { get; internal set; } 97 | public uint Cmd2T { get; internal set; } 98 | public uint CL { get; internal set; } 99 | public uint RCDWR { get; internal set; } 100 | public uint RCDRD { get; internal set; } 101 | public uint RP { get; internal set; } 102 | public uint RAS { get; internal set; } 103 | public uint RC { get; internal set; } 104 | public uint RRDS { get; internal set; } 105 | public uint RRDL { get; internal set; } 106 | public uint FAW { get; internal set; } 107 | public uint WTRS { get; internal set; } 108 | public uint WTRL { get; internal set; } 109 | public uint WR { get; internal set; } 110 | public uint RDRDSCL { get; internal set; } 111 | public uint WRWRSCL { get; internal set; } 112 | public uint CWL { get; internal set; } 113 | public uint RTP { get; internal set; } 114 | public uint RDWR { get; internal set; } 115 | public uint WRRD { get; internal set; } 116 | public uint RDRDSC { get; internal set; } 117 | public uint RDRDSD { get; internal set; } 118 | public uint RDRDDD { get; internal set; } 119 | public uint WRWRSC { get; internal set; } 120 | public uint WRWRSD { get; internal set; } 121 | public uint WRWRDD { get; internal set; } 122 | public uint TRCPAGE { get; internal set; } 123 | public uint CKE { get; internal set; } 124 | public uint STAG { get; internal set; } 125 | public uint MOD { get; internal set; } 126 | public uint MODPDA { get; internal set; } 127 | public uint MRD { get; internal set; } 128 | public uint MRDPDA { get; internal set; } 129 | public uint RFC { get; internal set; } 130 | public uint RFC2 { get; internal set; } 131 | public uint REFI { get; internal set; } 132 | public uint XP { get; internal set; } 133 | public uint PHYWRD { get; internal set; } 134 | public uint PHYWRL { get; internal set; } 135 | public uint PHYRDL { get; internal set; } 136 | public float RFCns { get => Utils.ToNanoseconds(RFC, Frequency); } 137 | public float REFIns { get => Utils.ToNanoseconds(REFI, Frequency); } 138 | 139 | protected virtual void Dispose(bool disposing) 140 | { 141 | if (!disposedValue) 142 | { 143 | Dict = null; 144 | disposedValue = true; 145 | } 146 | } 147 | 148 | public void Dispose() 149 | { 150 | Dispose(disposing: true); 151 | GC.SuppressFinalize(this); 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /DRAM/Capacity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using static ZenStates.Core.DRAM.MemoryConfig; 3 | 4 | namespace ZenStates.Core.DRAM 5 | { 6 | public class Capacity 7 | { 8 | public CapacityUnit Unit; 9 | public ulong SizeInBytes; 10 | 11 | public Capacity() 12 | { 13 | Unit = CapacityUnit.GB; 14 | SizeInBytes = 0; 15 | } 16 | 17 | public Capacity(ulong sizeInBytes, CapacityUnit unit = CapacityUnit.GB) 18 | { 19 | Unit = unit; 20 | SizeInBytes = sizeInBytes; 21 | } 22 | 23 | public override string ToString() 24 | { 25 | return $"{SizeInBytes / Math.Pow(1024, (int)Unit)}{Enum.GetName(typeof(CapacityUnit), Unit)}"; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DRAM/Ddr4Timings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using static ZenStates.Core.DRAM.MemoryConfig; 3 | 4 | namespace ZenStates.Core.DRAM 5 | { 6 | [Serializable] 7 | public class Ddr4Timings : BaseDramTimings 8 | { 9 | public Ddr4Timings(Cpu cpu) : base(cpu) 10 | { 11 | this.Type = MemType.DDR4; 12 | this.Dict = DDR4Dictionary.defs; 13 | } 14 | 15 | // Specific DDR4 timings 16 | public uint RFC4 { get; set; } 17 | 18 | public override void Read(uint offset = 0) 19 | { 20 | Ratio = Utils.GetBits(cpu.ReadDword(offset | 0x50200), 0, 7) / 3.0f; 21 | 22 | base.Read(offset); 23 | 24 | uint trfcTimings0 = this.cpu.ReadDword(offset | 0x50260); 25 | uint trfcTimings1 = this.cpu.ReadDword(offset | 0x50264); 26 | uint trfcRegValue = trfcTimings0 != trfcTimings1 ? (trfcTimings0 != 0x21060138 ? trfcTimings0 : trfcTimings1) : trfcTimings0; 27 | 28 | if (trfcRegValue != 0) 29 | { 30 | RFC = Utils.BitSlice(trfcRegValue, 10, 0); 31 | RFC2 = Utils.BitSlice(trfcRegValue, 21, 11); 32 | RFC4 = Utils.GetBits(trfcRegValue, 31, 22); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /DRAM/Ddr5Timings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using static ZenStates.Core.DRAM.MemoryConfig; 3 | 4 | namespace ZenStates.Core.DRAM 5 | { 6 | [Serializable] 7 | public class Ddr5Timings : BaseDramTimings 8 | { 9 | public readonly struct NitroSettings 10 | { 11 | public byte RxData { get; } 12 | public byte TxData { get; } 13 | public byte CtrlLine { get; } 14 | 15 | public NitroSettings(uint registerValue) 16 | { 17 | CtrlLine = (byte)(registerValue & 0x3); 18 | TxData = (byte)((registerValue >> 4) & 0x3); 19 | RxData = (byte)((registerValue >> 8) & 0x3); 20 | } 21 | 22 | public override string ToString() 23 | { 24 | return $"{RxData}/{TxData}/{CtrlLine}"; 25 | } 26 | } 27 | 28 | public Ddr5Timings(Cpu cpu) : base(cpu) 29 | { 30 | this.Type = MemType.DDR5; 31 | this.Dict = DDR5Dictionary.defs; 32 | } 33 | 34 | public uint RFCsb { get; private set; } 35 | 36 | public NitroSettings Nitro { get; private set; } 37 | 38 | public override void Read(uint offset = 0) 39 | { 40 | Ratio = Utils.BitSlice(cpu.ReadDword(offset | 0x50200), 15, 0) / 100.0f; 41 | 42 | base.Read(offset); 43 | 44 | // TRFC 45 | // define as separate variables to avoid false-positives on virus scans 46 | uint trfcTimings0 = cpu.ReadDword(offset | 0x50260); 47 | uint trfcTimings1 = cpu.ReadDword(offset | 0x50264); 48 | uint trfcTimings2 = cpu.ReadDword(offset | 0x50268); 49 | uint trfcTimings3 = cpu.ReadDword(offset | 0x5026C); 50 | uint trfcRegValue = 0; 51 | 52 | uint[] ddr5Regs = new[] { trfcTimings0, trfcTimings1, trfcTimings2, trfcTimings3 }; 53 | foreach (uint reg in ddr5Regs) 54 | { 55 | if (reg != 0x00C00138) 56 | { 57 | trfcRegValue = reg; 58 | break; 59 | } 60 | } 61 | 62 | if (trfcRegValue != 0) 63 | { 64 | RFC = Utils.BitSlice(trfcRegValue, 15, 0); 65 | RFC2 = Utils.BitSlice(trfcRegValue, 31, 16); 66 | } 67 | 68 | // TRFCsb 69 | trfcTimings0 = Utils.BitSlice(cpu.ReadDword(offset | 0x502c0), 10, 0); 70 | trfcTimings1 = Utils.BitSlice(cpu.ReadDword(offset | 0x502c4), 10, 0); 71 | trfcTimings2 = Utils.BitSlice(cpu.ReadDword(offset | 0x502c8), 10, 0); 72 | trfcTimings3 = Utils.BitSlice(cpu.ReadDword(offset | 0x502cc), 10, 0); 73 | ddr5Regs = new[] { trfcTimings0, trfcTimings1, trfcTimings2, trfcTimings3 }; 74 | 75 | foreach (uint value in ddr5Regs) 76 | { 77 | if (value != 0) 78 | { 79 | RFCsb = value; 80 | break; 81 | } 82 | } 83 | 84 | uint nitroSettings = Utils.BitSlice(cpu.ReadDword(offset | 0x50284), 11, 0); 85 | Nitro = new NitroSettings(nitroSettings); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /DRAM/IDramTimings.cs: -------------------------------------------------------------------------------- 1 | using static ZenStates.Core.DRAM.MemoryConfig; 2 | 3 | namespace ZenStates.Core.DRAM 4 | { 5 | public interface IDramTimings 6 | { 7 | // Properties 8 | MemType Type { get; } 9 | float Frequency { get; } 10 | float Ratio { get; } 11 | uint BGS { get; } 12 | uint BGSAlt { get; } 13 | uint GDM { get; } 14 | uint PowerDown { get; } 15 | uint Cmd2T { get; } 16 | uint CL { get; } 17 | uint RCDWR { get; } 18 | uint RCDRD { get; } 19 | uint RP { get; } 20 | uint RAS { get; } 21 | uint RC { get; } 22 | uint RRDS { get; } 23 | uint RRDL { get; } 24 | uint FAW { get; } 25 | uint WTRS { get; } 26 | uint WTRL { get; } 27 | uint WR { get; } 28 | uint RDRDSCL { get; } 29 | uint WRWRSCL { get; } 30 | uint CWL { get; } 31 | uint RTP { get; } 32 | uint RDWR { get; } 33 | uint WRRD { get; } 34 | uint RDRDSC { get; } 35 | uint RDRDSD { get; } 36 | uint RDRDDD { get; } 37 | uint WRWRSC { get; } 38 | uint WRWRSD { get; } 39 | uint WRWRDD { get; } 40 | uint TRCPAGE { get; } 41 | uint CKE { get; } 42 | uint STAG { get; } 43 | uint MOD { get; } 44 | uint MODPDA { get; } 45 | uint MRD { get; } 46 | uint MRDPDA { get; } 47 | 48 | // Methods 49 | void ReadBankGroupSwap(uint offset = 0); 50 | void Read(uint offset = 0); 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /DRAM/MemoryConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Management; 5 | 6 | namespace ZenStates.Core.DRAM 7 | { 8 | public class MemoryConfig 9 | { 10 | private const int DRAM_TYPE_BIT_MASK = 0x1; 11 | 12 | private const uint DRAM_TYPE_REG_ADDR = 0x50100; 13 | 14 | private const int MAX_CHANNELS = 12; 15 | 16 | private readonly uint ChannelsPerDimm; 17 | 18 | private readonly Cpu cpu; 19 | 20 | public struct Channel 21 | { 22 | public bool Enabled; 23 | 24 | public uint Offset; 25 | } 26 | 27 | public struct TimingDef 28 | { 29 | public string Name; 30 | 31 | public int HiBit; 32 | 33 | public int LoBit; 34 | } 35 | 36 | public enum MemType 37 | { 38 | DDR4 = 0, 39 | DDR5 = 1, 40 | LPDDR5 = 2, 41 | } 42 | 43 | public enum CapacityUnit 44 | { 45 | B = 0, 46 | KB = 1, 47 | MB = 2, 48 | GB = 3, 49 | } 50 | 51 | public MemType Type { get; protected set; } 52 | 53 | public Capacity TotalCapacity { get; protected set; } 54 | 55 | public List> Timings { get; protected set; } 56 | 57 | public List Channels { get; protected set; } 58 | 59 | public List Modules { get; protected set; } 60 | 61 | public MemoryConfig(Cpu cpuInstance) 62 | { 63 | cpu = cpuInstance; 64 | 65 | Type = (MemType)(cpu.ReadDword(0 | DRAM_TYPE_REG_ADDR) & DRAM_TYPE_BIT_MASK); 66 | 67 | ChannelsPerDimm = 1; // Type == MemType.DDR5 ? 2u : 1u; 68 | 69 | Channels = new List(); 70 | 71 | Modules = new List(); 72 | 73 | ReadModulesInfo(); 74 | 75 | ReadChannels(); 76 | 77 | Timings = new List>(); 78 | 79 | foreach (MemoryModule module in Modules) 80 | { 81 | if (Type == MemType.DDR4) 82 | Timings.Add(new KeyValuePair(module.DctOffset, new Ddr4Timings(cpu))); 83 | else if (Type == MemType.DDR5) 84 | Timings.Add(new KeyValuePair(module.DctOffset, new Ddr5Timings(cpu))); 85 | 86 | ReadTimings(module.DctOffset); 87 | } 88 | } 89 | 90 | public void ReadTimings(uint offset = 0) 91 | { 92 | foreach (var item in Timings) 93 | { 94 | if (item.Key == offset) 95 | { 96 | item.Value.Read(offset); 97 | break; 98 | } 99 | } 100 | } 101 | 102 | private void ReadModulesInfo() 103 | { 104 | using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_PhysicalMemory")) 105 | { 106 | bool connected = false; 107 | 108 | try 109 | { 110 | WMI.Connect(@"root\cimv2"); 111 | 112 | connected = true; 113 | 114 | foreach (var qo in searcher.Get()) 115 | { 116 | var capacity = 0UL; 117 | var clockSpeed = 0U; 118 | var partNumber = "N/A"; 119 | var bankLabel = ""; 120 | var manufacturer = ""; 121 | var deviceLocator = ""; 122 | 123 | var queryObject = (ManagementObject)qo; 124 | 125 | var temp = WMI.TryGetProperty(queryObject, "Capacity"); 126 | if (temp != null) capacity = (ulong)temp; 127 | 128 | temp = WMI.TryGetProperty(queryObject, "partNumber"); 129 | if (temp != null) partNumber = (string)temp; 130 | 131 | temp = WMI.TryGetProperty(queryObject, "BankLabel"); 132 | if (temp != null) bankLabel = (string)temp; 133 | 134 | temp = WMI.TryGetProperty(queryObject, "Manufacturer"); 135 | if (temp != null) manufacturer = (string)temp; 136 | 137 | temp = WMI.TryGetProperty(queryObject, "DeviceLocator"); 138 | if (temp != null) deviceLocator = (string)temp; 139 | 140 | temp = WMI.TryGetProperty(queryObject, "ConfiguredClockSpeed"); 141 | if (temp != null) clockSpeed = (uint)temp; 142 | 143 | Modules.Add(new MemoryModule(partNumber.Trim(), bankLabel.Trim(), manufacturer.Trim(), 144 | deviceLocator, capacity, clockSpeed)); 145 | 146 | //string bl = bankLabel.Length > 0 ? new string(bankLabel.Where(char.IsDigit).ToArray()) : ""; 147 | //string dl = deviceLocator.Length > 0 ? new string(deviceLocator.Where(char.IsDigit).ToArray()) : ""; 148 | 149 | //comboBoxPartNumber.Items.Add($"#{bl}: {partNumber}"); 150 | //comboBoxPartNumber.SelectedIndex = 0; 151 | } 152 | } 153 | catch (Exception ex) 154 | { 155 | //throw new ApplicationException(connected ? @"Failed to get installed memory parameters." : $@"{ex.Message}"); 156 | Debug.WriteLine(connected ? @"Failed to get installed memory parameters." : $@"{ex.Message}"); 157 | } 158 | 159 | if (Modules?.Count > 0) 160 | { 161 | ulong totalCapacity = 0UL; 162 | foreach (MemoryModule module in Modules) 163 | { 164 | totalCapacity += module.Capacity.SizeInBytes; 165 | } 166 | TotalCapacity = new Capacity(totalCapacity); 167 | } 168 | } 169 | } 170 | 171 | private MemRank GetRank(uint address) 172 | { 173 | if (Type == MemType.DDR4) 174 | { 175 | return (MemRank)Utils.GetBits(cpu.ReadDword(address), 0, 1); 176 | } 177 | else if (Type == MemType.DDR5 || Type == MemType.LPDDR5) 178 | { 179 | var value = cpu.ReadDword(address); 180 | if (value != 0 && value == 0x07FFFBFE) 181 | return MemRank.DR; 182 | value = cpu.ReadDword(address + 4); 183 | if (value != 0 && value == 0x07FFFBFE) 184 | return MemRank.DR; 185 | } 186 | 187 | return MemRank.SR; 188 | } 189 | 190 | private DramAddressConfig GetAddressConfig(uint address) 191 | { 192 | var value = cpu.ReadDword(address); 193 | var config = new DramAddressConfig(); 194 | if (value != 0) 195 | { 196 | config.NumBanks = Utils.GetBits(value, 20, 2); 197 | config.NumCol = 5 + Utils.GetBits(value, 16, 4); 198 | config.NumRow = 10 + Utils.GetBits(value, 8, 4); 199 | config.NumRM = Utils.GetBits(value, 4, 3); 200 | config.NumBankGroups = Utils.GetBits(value, 2, 2); 201 | config.Rank = GetRank(address - 0x20); 202 | } 203 | return config; 204 | } 205 | 206 | private void ReadChannels() 207 | { 208 | int dimmIndex = 0; 209 | uint dimmsPerChannel = 1; 210 | 211 | // Get the offset by probing the UMC0 to UMC7 212 | // It appears that offsets 0x80 and 0x84 are DIMM config registers 213 | // When a DIMM is DR, bit 0 is set to 1 214 | // 0x50000 215 | // offset 0, bit 0 when set to 1 means DIMM1 is installed 216 | // offset 8, bit 0 when set to 1 means DIMM2 is installed 217 | for (uint i = 0; i < MAX_CHANNELS * ChannelsPerDimm; i += ChannelsPerDimm) 218 | { 219 | try 220 | { 221 | uint offset = i << 20; 222 | bool channel = Utils.GetBits(cpu.ReadDword(offset | 0x50DF0), 19, 1) == 0; 223 | bool dimm1 = Utils.GetBits(cpu.ReadDword(offset | 0x50000), 0, 1) == 1; 224 | bool dimm2 = Utils.GetBits(cpu.ReadDword(offset | 0x50008), 0, 1) == 1; 225 | bool enabled = channel && (dimm1 || dimm2); 226 | 227 | Channels.Add(new Channel() 228 | { 229 | Enabled = enabled, 230 | Offset = offset, 231 | }); 232 | 233 | if (enabled) 234 | { 235 | if (dimm1) 236 | { 237 | MemoryModule module = Modules[dimmIndex++]; 238 | module.Slot = $"{Convert.ToChar(i / ChannelsPerDimm + 65)}1"; 239 | module.DctOffset = offset; 240 | module.Rank = (Type == MemType.DDR4) ? GetRank(offset | 0x50080) : GetRank(offset | 0x50020); 241 | module.AddressConfig = GetAddressConfig(offset | 0x50040); 242 | } 243 | 244 | if (dimm2) 245 | { 246 | MemoryModule module = Modules[dimmIndex++]; 247 | module.Slot = $"{Convert.ToChar(i / ChannelsPerDimm + 65)}2"; 248 | module.DctOffset = offset; 249 | module.Rank = (Type == MemType.DDR4) ? GetRank(offset | 0x50084) : GetRank(offset | 0x50028); 250 | module.AddressConfig = GetAddressConfig(offset | 0x50048); 251 | } 252 | } 253 | } 254 | catch 255 | { 256 | // do nothing 257 | } 258 | } 259 | } 260 | } 261 | } 262 | /* 263 | 0x0025060c 264 | 0x25060c 0010 0101 0000 0110 0000 1100 265 | numBanks[21:20] 32 banks(2h) 266 | numCol[19:16] 10 + 5 267 | NumRow[11:8] 10 + 6 268 | numRM[6:4] 0 269 | bank groups 8 (3h) 270 | 271 | > 0x00150508 272 | 0x150508 0001 0101 0000 0101 0000 1000 273 | numBanks [21:20] 32 banks (2h) 274 | numCol [19:16] 10 + 5 275 | NumRow [11:8] 10 + 5 276 | numRM [6:4] 0 277 | bank groups [3:2] 4 (2h) 278 | 279 | */ -------------------------------------------------------------------------------- /DRAM/MemoryModule.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | 3 | namespace ZenStates.Core.DRAM 4 | { 5 | public enum MemRank 6 | { 7 | SR = 0, 8 | DR = 1, 9 | QR = 2, 10 | } 11 | 12 | public struct DramAddressConfig 13 | { 14 | public MemRank Rank { get; set; } 15 | public uint NumBanks { get; set; } 16 | public uint NumCol { get; set; } 17 | public uint NumRow { get; set; } 18 | public uint NumRM { get; set; } 19 | public uint NumBankGroups { get; set; } 20 | private static string GetBankDescription(uint value) 21 | { 22 | switch (value) 23 | { 24 | case 0x0: 25 | return "8 Banks (3 bit)"; 26 | case 0x1: 27 | return "16 Banks (4 bit)"; 28 | case 0x2: 29 | return "32 Banks (5 bit)"; 30 | case 0x3: 31 | return "64 Banks (6 bit)"; 32 | default: 33 | return "Unknown Bank Configuration"; 34 | } 35 | } 36 | 37 | private static string GetBankGroupDescription(uint value) 38 | { 39 | switch (value) 40 | { 41 | case 0x0: 42 | return "No Bank Groups (0 bit)"; 43 | case 0x1: 44 | return "2 Bank Groups (1 bit)"; 45 | case 0x2: 46 | return "4 Bank Groups (2 bit)"; 47 | case 0x3: 48 | return "8 Bank Groups (3 bit)"; 49 | default: 50 | return "Unknown Bank Group Configuration"; 51 | } 52 | } 53 | 54 | private static string GetRmDescription(uint value) 55 | { 56 | switch (value) 57 | { 58 | case 0x0: 59 | return "No RM (0 bit)"; 60 | case 0x1: 61 | return "2x RM (1 bit)"; 62 | case 0x2: 63 | return "4x RM (2 bit)"; 64 | case 0x3: 65 | return "8x RM (3 bit)"; 66 | default: 67 | return "Unknown RM Configuration"; 68 | } 69 | } 70 | 71 | 72 | public override string ToString() 73 | { 74 | return $"{GetBankDescription(NumBanks)}, Col: {NumCol}, Row: {NumRow}, {GetRmDescription(NumRM)}, {GetBankGroupDescription(NumBankGroups)}"; 75 | } 76 | } 77 | 78 | 79 | public readonly struct DimmConfiguration 80 | { 81 | public bool PkgRnkTimingAlign { get; } 82 | public bool DimmRefDis { get; } 83 | public bool DqMapSwapDis { get; } 84 | public bool X16Dram { get; } 85 | public bool X4Dram { get; } 86 | public bool LRDIMM { get; } 87 | public bool RDIMM { get; } 88 | public bool CIsCS { get; } 89 | public bool Dram3DS { get; } 90 | public bool OutputInvert { get; } 91 | public bool OnDimmMirror { get; } 92 | 93 | public DimmConfiguration(int value) 94 | { 95 | PkgRnkTimingAlign = (value & (1 << 10)) != 0; 96 | DimmRefDis = (value & (1 << 9)) != 0; 97 | DqMapSwapDis = (value & (1 << 8)) != 0; 98 | X16Dram = (value & (1 << 7)) != 0; 99 | X4Dram = (value & (1 << 6)) != 0; 100 | LRDIMM = (value & (1 << 5)) != 0; 101 | RDIMM = (value & (1 << 4)) != 0; 102 | CIsCS = (value & (1 << 3)) != 0; 103 | Dram3DS = (value & (1 << 2)) != 0; 104 | OutputInvert = (value & (1 << 1)) != 0; 105 | OnDimmMirror = (value & (1 << 0)) != 0; 106 | } 107 | 108 | public override string ToString() 109 | { 110 | return 111 | $"PkgRnkTimingAlign: {(PkgRnkTimingAlign ? "Enabled" : "Disabled")}\n" + 112 | $"DimmRefDis: {(DimmRefDis ? "Disabled" : "Enabled")}\n" + 113 | $"DqMapSwapDis: {(DqMapSwapDis ? "Disabled" : "Enabled")}\n" + 114 | $"X16Dram: {(X16Dram ? "Enabled" : "Disabled")}\n" + 115 | $"X4Dram: {(X4Dram ? "Enabled" : "Disabled")}\n" + 116 | $"LRDIMM: {(LRDIMM ? "Enabled" : "Disabled")}\n" + 117 | $"RDIMM: {(RDIMM ? "Enabled" : "Disabled")}\n" + 118 | $"CIsCS: {(CIsCS ? "Enabled" : "Disabled")}\n" + 119 | $"Dram3DS: {(Dram3DS ? "Enabled" : "Disabled")}\n" + 120 | $"OutputInvert: {(OutputInvert ? "Enabled" : "Disabled")}\n" + 121 | $"OnDimmMirror: {(OnDimmMirror ? "Enabled" : "Disabled")}"; 122 | } 123 | } 124 | 125 | public class MemoryModule : IEnumerable 126 | { 127 | public string BankLabel { get; set; } 128 | public string PartNumber { get; set; } 129 | public string Manufacturer { get; set; } 130 | public string DeviceLocator { get; set; } 131 | public Capacity Capacity { get; set; } 132 | public uint ClockSpeed { get; set; } 133 | public MemRank Rank { get; set; } 134 | public string Slot { get; set; } = ""; 135 | public uint DctOffset { get; set; } = 0; 136 | public DramAddressConfig AddressConfig { get; set; } 137 | 138 | public MemoryModule() 139 | { 140 | Capacity = new Capacity(); 141 | } 142 | 143 | public MemoryModule(string partNumber, string bankLabel, string manufacturer, 144 | string deviceLocator, ulong capacity, uint clockSpeed) 145 | { 146 | PartNumber = partNumber; 147 | Capacity = new Capacity(capacity); 148 | ClockSpeed = clockSpeed; 149 | BankLabel = bankLabel; 150 | Manufacturer = manufacturer; 151 | DeviceLocator = deviceLocator; 152 | } 153 | 154 | public IEnumerator GetEnumerator() 155 | { 156 | return ((IEnumerable)PartNumber).GetEnumerator(); 157 | } 158 | 159 | public override string ToString() 160 | { 161 | return $"{Slot}: {PartNumber} ({Capacity}, {Rank})"; 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /Dictionaries/AodDictionaries.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace ZenStates.Core 4 | { 5 | internal sealed class AodDictionaries 6 | { 7 | // CPU On-Die Termination 8 | public static readonly Dictionary ProcOdtDict = new Dictionary 9 | { 10 | {0, "Hi-Z"}, 11 | {1, "480.0 Ω"}, 12 | {2, "240.0 Ω"}, 13 | {3, "160.0 Ω"}, 14 | {4, "120.0 Ω"}, 15 | {5, "96.0 Ω"}, 16 | {6, "80.0 Ω"}, 17 | {7, "68.6 Ω"}, 18 | {12, "60.0 Ω"}, 19 | {13, "53.3 Ω"}, 20 | {14, "48.0 Ω"}, 21 | {15, "43.6 Ω"}, 22 | {28, "40.0 Ω"}, 23 | {29, "36.9 Ω"}, 24 | {30, "34.3 Ω"}, 25 | {31, "32.0 Ω"}, 26 | {60, "30.0 Ω"}, 27 | {61, "28.2 Ω"}, 28 | {62, "26.7 Ω"}, 29 | {63, "25.3 Ω"}, 30 | }; 31 | 32 | // Proc Data Drive Strength 33 | public static readonly Dictionary ProcDataDrvStrenDict = new Dictionary 34 | { 35 | {0, "Hi-Z"}, 36 | {2, "240.0 Ω"}, 37 | {4, "120.0 Ω"}, 38 | {6, "80.0 Ω"}, 39 | {12, "60.0 Ω"}, 40 | {14, "48.0 Ω"}, 41 | {28, "40.0 Ω"}, 42 | {30, "34.3 Ω"}, 43 | }; 44 | 45 | // DRAM Data Drive Strength 46 | public static readonly Dictionary DramDataDrvStrenDict = new Dictionary 47 | { 48 | {0, "34.0 Ω"}, 49 | {1, "40.0 Ω"}, 50 | {2, "48.0 Ω"}, 51 | }; 52 | 53 | // Proc Data Drive Strength 54 | public static readonly Dictionary CadBusDrvStrenDict = new Dictionary 55 | { 56 | {0, "Hi-Z" }, 57 | {30, "30.0 Ω"}, 58 | {40, "40.0 Ω"}, 59 | {60, "60.0 Ω"}, 60 | {120, "120.0 Ω"}, 61 | }; 62 | 63 | // Proc CA ODT impedance 64 | // Proc CK ODT impedance 65 | // Proc DQ ODT impedance 66 | // Proc DQS ODT impedance 67 | public static readonly Dictionary ProcOdtImpedanceDict = new Dictionary 68 | { 69 | {0, "Off" }, 70 | {30, "30.0 Ω"}, 71 | {40, "40.0 Ω"}, 72 | {60, "60.0 Ω"}, 73 | {120, "120.0 Ω"}, 74 | }; 75 | 76 | // RttNom, RttPark 77 | public static readonly Dictionary RttDict = new Dictionary 78 | { 79 | {0, "Off"}, 80 | {1, "RZQ/1"}, 81 | {2, "RZQ/2"}, 82 | {3, "RZQ/3"}, 83 | {4, "RZQ/4"}, 84 | {5, "RZQ/5"}, 85 | {6, "RZQ/6"}, 86 | {7, "RZQ/7"}, 87 | }; 88 | 89 | public static readonly Dictionary AodDataDictionaryV1 = new Dictionary 90 | { 91 | { "SMTEn", 8920 }, 92 | { "MemClk", 8924 }, 93 | { "Tcl", 8928 }, 94 | { "Trcd", 8932 }, 95 | { "Trp", 8936 }, 96 | { "Tras", 8940 }, 97 | { "Trc", 8944 }, 98 | { "Twr", 8948 }, 99 | { "Trfc", 8952 }, 100 | { "Trfc2", 8956 }, 101 | { "Trfcsb", 8960 }, 102 | { "Trtp", 8964 }, 103 | { "TrrdL", 8968 }, 104 | { "TrrdS", 8972 }, 105 | { "Tfaw", 8976 }, 106 | { "TwtrL", 8980 }, 107 | { "TwtrS", 8984 }, 108 | { "TrdrdScL", 8988 }, 109 | { "TrdrdSc", 8992 }, 110 | { "TrdrdSd", 8996 }, 111 | { "TrdrdDd", 9000 }, 112 | { "TwrwrScL", 9004 }, 113 | { "TwrwrSc", 9008 }, 114 | { "TwrwrSd", 9012 }, 115 | { "TwrwrDd", 9016 }, 116 | { "Twrrd", 9020 }, 117 | { "Trdwr", 9024 }, 118 | { "CadBusDrvStren", 9028 }, 119 | { "ProcDataDrvStren", 9032 }, 120 | { "ProcOdt", 9036 }, 121 | { "DramDataDrvStren", 9040 }, 122 | { "RttNomWr", 9044 }, 123 | { "RttNomRd", 9048 }, 124 | { "RttWr", 9052 }, 125 | { "RttPark", 9056 }, 126 | { "RttParkDqs", 9060 }, 127 | { "MemVddio", 9096 }, 128 | { "MemVddq", 9100 }, 129 | { "MemVpp", 9104 }, 130 | { "ApuVddio", 9108 } 131 | }; 132 | 133 | public static readonly Dictionary AodDataDictionaryV2 = new Dictionary 134 | { 135 | { "SMTEn", 8916 }, 136 | { "MemClk", 8920 }, 137 | { "Tcl", 8924 }, 138 | { "Trcd", 8928 }, 139 | { "Trp", 8932 }, 140 | { "Tras", 8936 }, 141 | { "Trc", 8940 }, 142 | { "Twr", 8944 }, 143 | { "Trfc", 8948 }, 144 | { "Trfc2", 8952 }, 145 | { "Trfcsb", 8956 }, 146 | { "Trtp", 8960 }, 147 | { "TrrdL", 8964 }, 148 | { "TrrdS", 8968 }, 149 | { "Tfaw", 8972 }, 150 | { "TwtrL", 8976 }, 151 | { "TwtrS", 8980 }, 152 | { "TrdrdScL", 8984 }, 153 | { "TrdrdSc", 8988 }, 154 | { "TrdrdSd", 8992 }, 155 | { "TrdrdDd", 9096 }, 156 | { "TwrwrScL", 9000 }, 157 | { "TwrwrSc", 9004 }, 158 | { "TwrwrSd", 9008 }, 159 | { "TwrwrDd", 9012 }, 160 | { "Twrrd", 9016 }, 161 | { "Trdwr", 9020 }, 162 | { "CadBusDrvStren", 9024 }, 163 | { "ProcDataDrvStren", 9028 }, 164 | { "ProcOdt", 9032 }, 165 | { "DramDataDrvStren", 9036 }, 166 | { "RttNomWr", 9040 }, 167 | { "RttNomRd", 9044 }, 168 | { "RttWr", 9048 }, 169 | { "RttPark", 9052 }, 170 | { "RttParkDqs", 9056 }, 171 | { "MemVddio", 9092 }, 172 | { "MemVddq", 9096 }, 173 | { "MemVpp", 9100 }, 174 | { "ApuVddio", 9104 } 175 | }; 176 | 177 | public static readonly Dictionary AodDataDictionaryV3 = new Dictionary 178 | { 179 | { "SMTEn", 8968 }, 180 | { "MemClk", 8976 }, 181 | { "Tcl", 8988 }, 182 | { "TrcdWr", 8992 }, 183 | { "TrcdRd", 8996 }, 184 | { "Trp", 9000 }, 185 | { "Trfc", 9004 }, 186 | { "Tras", 9008 }, 187 | { "Trc", 9012 }, 188 | { "TrrdS", 9016 }, 189 | { "TrrdL", 9020 }, 190 | { "Tfaw", 9024 }, 191 | { "TwtrL", 9028 }, 192 | { "TwtrS", 9032 }, 193 | { "Twr", 9036 }, 194 | { "TrdrdScL", 9040 }, 195 | { "TwrwrScL", 9044 }, 196 | { "Trtp", 9048 }, 197 | { "Tcke", 9052 }, 198 | { "TrdrdSc", 9056 }, 199 | { "TrdrdSd", 9060 }, 200 | { "TrdrdDd", 9064 }, 201 | { "TwrwrSc", 9068 }, 202 | { "TwrwrSd", 9072 }, 203 | { "TwrwrDd", 9076 }, 204 | { "Twrrd", 9080 }, 205 | { "Trdwr", 9084 }, 206 | { "CadBusDrvStren", 9088 }, 207 | { "ProcDataDrvStren", 9092 }, 208 | { "ProcOdt", 9096 }, 209 | { "DramDataDrvStren", 9100 }, 210 | { "RttNomWr", 9104 }, 211 | { "RttNomRd", 9108 }, 212 | { "RttWr", 9112 }, 213 | { "RttPark", 9116 }, 214 | { "RttParkDqs", 9120 }, 215 | { "MemVddio", 9156 }, 216 | { "MemVddq", 9160 }, 217 | { "MemVpp", 9164 }, 218 | { "ApuVddio", 9168 } 219 | }; 220 | 221 | // Phoenix, HawkPoint 222 | public static readonly Dictionary AodDataDictionaryV4 = new Dictionary 223 | { 224 | { "SMTEn", 8916 }, 225 | { "MemClk", 8920 }, 226 | { "Tcl", 8924 }, 227 | { "Trcd", 8928 }, 228 | { "Trp", 8932 }, 229 | { "Tras", 8936 }, 230 | { "Trc", 8940 }, 231 | { "Twr", 8944 }, 232 | { "Trfc", 8948 }, 233 | { "Trfc2", 8952 }, 234 | { "Trfcsb", 8956 }, 235 | { "Trtp", 8960 }, 236 | { "TrrdL", 8964 }, 237 | { "TrrdS", 8968 }, 238 | { "Tfaw", 8972 }, 239 | { "TwtrL", 8976 }, 240 | { "TwtrS", 8980 }, 241 | { "TrdrdScL", 8984 }, 242 | { "TrdrdSc", 8988 }, 243 | { "TrdrdSd", 8992 }, 244 | { "TrdrdDd", 8996 }, 245 | { "TwrwrScL", 9000 }, 246 | { "TwrwrSc", 9004 }, 247 | { "TwrwrSd", 9008 }, 248 | { "TwrwrDd", 9012 }, 249 | { "Twrrd", 9016 }, 250 | { "Trdwr", 9020 }, 251 | { "CadBusDrvStren", 9024 }, 252 | { "ProcDataDrvStren", 9028 }, 253 | { "ProcCaOdt", 9032 }, 254 | { "ProcCkOdt", 9036 }, 255 | { "ProcDqOdt", 9040 }, 256 | { "ProcDqsOdt", 9044 }, 257 | { "DramDataDrvStren", 9048 }, 258 | { "RttNomWr", 9052 }, 259 | { "RttNomRd", 9056 }, 260 | { "RttWr", 9060 }, 261 | { "RttPark", 9064 }, 262 | { "RttParkDqs", 9068 }, 263 | { "MemVddio", 9116 }, 264 | { "MemVddq", 9120 }, 265 | { "MemVpp", 9124 }, 266 | { "ApuVddio", 9128 } 267 | }; 268 | 269 | // GraniteRidge 270 | 271 | public static readonly Dictionary BaseAodDataDictionary_1Ah = new Dictionary 272 | { 273 | { "SMTEn", 8920 }, 274 | { "MemClk", 8924 }, 275 | { "Tcl", 8928 }, 276 | { "Trcd", 8932 }, 277 | { "Trp", 8936 }, 278 | { "Tras", 8940 }, 279 | { "Trc", 8944 }, 280 | { "Twr", 8948 }, 281 | { "Trfc", 8952 }, 282 | { "Trfc2", 8956 }, 283 | { "Trfcsb", 8960 }, 284 | { "Trtp", 8964 }, 285 | { "TrrdL", 8968 }, 286 | { "TrrdS", 8972 }, 287 | { "Tfaw", 8976 }, 288 | { "TwtrL", 8980 }, 289 | { "TwtrS", 8984 }, 290 | { "TrdrdScL", 8988 }, 291 | { "TrdrdSc", 8992 }, 292 | { "TrdrdSd", 8996 }, 293 | { "TrdrdDd", 9000 }, 294 | { "TwrwrScL", 9004 }, 295 | { "TwrwrSc", 9008 }, 296 | { "TwrwrSd", 9012 }, 297 | { "TwrwrDd", 9016 }, 298 | { "Twrrd", 9020 }, 299 | { "Trdwr", 9024 }, 300 | }; 301 | 302 | public static readonly Dictionary AodDataDictionary_1Ah = new Dictionary(BaseAodDataDictionary_1Ah) 303 | { 304 | { "CadBusDrvStren", 9028 }, 305 | { "ProcDataDrvStren", 9032 }, 306 | 307 | { "RttNomWr", 9036 }, 308 | { "RttNomRd", 9040 }, 309 | { "RttWr", 9044 }, 310 | { "RttPark", 9048 }, 311 | { "RttParkDqs", 9052 }, 312 | 313 | { "MemVddio", 9088 }, 314 | { "MemVddq", 9092 }, 315 | { "MemVpp", 9096 }, 316 | { "ApuVddio", 9100 }, 317 | 318 | { "ProcOdt", 9164 }, 319 | { "ProcOdtPullUp", 9164 }, 320 | { "ProcOdtPullDown", 9168 }, 321 | { "DramDataDrvStren", 9172 } 322 | }; 323 | 324 | public static readonly Dictionary AodDataDictionary_1Ah_B404023 = new Dictionary(BaseAodDataDictionary_1Ah) 325 | { 326 | { "CadBusDrvStren", 9028 }, 327 | 328 | { "RttNomWr", 9032 }, 329 | { "RttNomRd", 9036 }, 330 | { "RttWr", 9040 }, 331 | { "RttPark", 9044 }, 332 | { "RttParkDqs", 9048 }, 333 | 334 | { "MemVddio", 9084 }, 335 | { "MemVddq", 9088 }, 336 | { "MemVpp", 9092 }, 337 | { "ApuVddio", 9096 }, 338 | 339 | { "ProcOdt", 9172 }, 340 | { "ProcOdtPullUp", 9172 }, 341 | { "ProcOdtPullDown", 9176 }, 342 | { "DramDataDrvStren", 9180 }, 343 | { "ProcDataDrvStren", 9196 }, 344 | }; 345 | 346 | // M-Die 24GB SR sticks 347 | public static readonly Dictionary AodDataDictionary_1Ah_M = new Dictionary(BaseAodDataDictionary_1Ah) 348 | { 349 | { "CadBusDrvStren", 9028 }, 350 | { "ProcDataDrvStren", 9032 }, 351 | 352 | { "RttNomWr", 9036 }, 353 | { "RttNomRd", 9040 }, 354 | { "RttWr", 9044 }, 355 | { "RttPark", 9048 }, 356 | { "RttParkDqs", 9052 }, 357 | 358 | { "MemVddio", 9088 }, 359 | { "MemVddq", 9092 }, 360 | { "MemVpp", 9096 }, 361 | { "ApuVddio", 9100 }, 362 | 363 | { "ProcOdt", 9176 }, 364 | { "ProcOdtPullUp", 9176 }, 365 | { "ProcOdtPullDown", 9180 }, 366 | { "DramDataDrvStren", 9184 }, 367 | }; 368 | 369 | public static readonly Dictionary AodDataDictionary_1Ah_B404023_M = new Dictionary(BaseAodDataDictionary_1Ah) 370 | { 371 | { "CadBusDrvStren", 9028 }, 372 | 373 | { "RttNomWr", 9032 }, 374 | { "RttNomRd", 9036 }, 375 | { "RttWr", 9040 }, 376 | { "RttPark", 9044 }, 377 | { "RttParkDqs", 9048 }, 378 | 379 | { "MemVddio", 9084 }, 380 | { "MemVddq", 9088 }, 381 | { "MemVpp", 9092 }, 382 | { "ApuVddio", 9096 }, 383 | 384 | { "ProcOdt", 9160 }, 385 | { "ProcOdtPullUp", 9160 }, 386 | { "ProcOdtPullDown", 9164 }, 387 | { "DramDataDrvStren", 9168 }, 388 | { "ProcDataDrvStren", 9176 } 389 | }; 390 | } 391 | } -------------------------------------------------------------------------------- /Dictionaries/DDR4Dictionary.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using static ZenStates.Core.DRAM.MemoryConfig; 3 | 4 | namespace ZenStates.Core 5 | { 6 | internal static class DDR4Dictionary 7 | { 8 | public static readonly Dictionary defs = new Dictionary 9 | { 10 | /* 11 | // BGS0 12 | { 0x50050, new[] { 13 | new TimingDef { Name = "BGS0", HiBit = 31, LoBit = 0 }, 14 | }}, 15 | // BGS1 16 | { 0x50058, new[] { 17 | new TimingDef { Name = "BGS1", HiBit = 31, LoBit = 0 }, 18 | }}, 19 | { 0x500D0, new[] { 20 | new TimingDef { Name = "BGSAlt0", HiBit = 10 , LoBit = 4 }, 21 | }}, 22 | { 0x500D4, new[] { 23 | new TimingDef { Name = "BGSAlt1", HiBit = 10 , LoBit = 4 }, 24 | }}, 25 | */ 26 | { 0x5012C, new[] { 27 | new TimingDef { Name = "PowerDown", HiBit = 28 , LoBit = 28 }, 28 | }}, 29 | { 0x50200, new[] { 30 | new TimingDef { Name = "Cmd2T", HiBit = 10 , LoBit = 10 }, 31 | new TimingDef { Name = "GDM", HiBit = 11 , LoBit = 11 }, 32 | // new TimingDef { Name = "Ratio", HiBit = 6 , LoBit = 0 }, 33 | }}, 34 | { 0x50204, new[] { 35 | new TimingDef { Name = "RCDWR", HiBit = 29 , LoBit = 24 }, 36 | new TimingDef { Name = "RCDRD", HiBit = 21 , LoBit = 16 }, 37 | new TimingDef { Name = "RAS", HiBit = 14 , LoBit = 8 }, 38 | new TimingDef { Name = "CL", HiBit = 5 , LoBit = 0 }, 39 | }}, 40 | { 0x50208, new[] { 41 | new TimingDef { Name = "RC", HiBit = 7 , LoBit = 0 }, 42 | new TimingDef { Name = "RP", HiBit = 21 , LoBit = 16 }, 43 | }}, 44 | { 0x5020C, new[] { 45 | new TimingDef { Name = "RTP", HiBit = 28 , LoBit = 24 }, 46 | new TimingDef { Name = "RRDL", HiBit = 12 , LoBit = 8 }, 47 | new TimingDef { Name = "RRDS", HiBit = 4 , LoBit = 0 }, 48 | }}, 49 | { 0x50210, new[] { 50 | new TimingDef { Name = "FAW", HiBit = 7 , LoBit = 0 }, 51 | }}, 52 | { 0x50214, new[] { 53 | new TimingDef { Name = "WTRL", HiBit = 22 , LoBit = 16 }, 54 | new TimingDef { Name = "WTRS", HiBit = 12 , LoBit = 8 }, 55 | new TimingDef { Name = "CWL", HiBit = 5 , LoBit = 0 }, 56 | }}, 57 | { 0x50218, new[] { 58 | new TimingDef { Name = "WR", HiBit = 7 , LoBit = 0 }, 59 | }}, 60 | { 0x5021C, new[] { 61 | new TimingDef { Name = "TRCPAGE", HiBit = 31 , LoBit = 20 }, // ? 62 | }}, 63 | { 0x50220, new[] { 64 | new TimingDef { Name = "RDRDSCL", HiBit = 29 , LoBit = 24 }, // ? 65 | new TimingDef { Name = "RDRDSC", HiBit = 19 , LoBit = 16 }, 66 | new TimingDef { Name = "RDRDSD", HiBit = 11 , LoBit = 8 }, 67 | new TimingDef { Name = "RDRDDD", HiBit = 3 , LoBit = 0 }, 68 | }}, 69 | { 0x50224, new[] { 70 | new TimingDef { Name = "WRWRSCL", HiBit = 29 , LoBit = 24 }, // ? 71 | new TimingDef { Name = "WRWRSC", HiBit = 19 , LoBit = 16 }, 72 | new TimingDef { Name = "WRWRSD", HiBit = 11 , LoBit = 8 }, 73 | new TimingDef { Name = "WRWRDD", HiBit = 3 , LoBit = 0 }, 74 | }}, 75 | { 0x50228, new[] { 76 | new TimingDef { Name = "RDWR", HiBit = 13 , LoBit = 8 }, 77 | new TimingDef { Name = "WRRD", HiBit = 3 , LoBit = 0 }, 78 | }}, 79 | { 0x50230, new[] { 80 | new TimingDef { Name = "REFI", HiBit = 15 , LoBit = 0 }, 81 | }}, 82 | { 0x50234, new[] { 83 | new TimingDef { Name = "MODPDA", HiBit = 29 , LoBit = 24 }, 84 | new TimingDef { Name = "MRDPDA", HiBit = 21 , LoBit = 16 }, 85 | new TimingDef { Name = "MOD", HiBit = 13 , LoBit = 8 }, 86 | new TimingDef { Name = "MRD", HiBit = 5 , LoBit = 0 }, 87 | }}, 88 | { 0x50250, new[] { 89 | new TimingDef { Name = "STAG", HiBit = 26 , LoBit = 16 }, 90 | }}, 91 | { 0x50254, new[] { 92 | new TimingDef { Name = "CKE", HiBit = 28 , LoBit = 24 }, 93 | new TimingDef { Name = "XP", HiBit = 5 , LoBit = 0 }, 94 | }}, 95 | { 0x50258, new[] { 96 | new TimingDef { Name = "PHYWRD", HiBit = 26 , LoBit = 24 }, 97 | new TimingDef { Name = "PHYRDL", HiBit = 23 , LoBit = 16 }, 98 | new TimingDef { Name = "PHYWRL", HiBit = 15 , LoBit = 8 }, 99 | }}, 100 | // TRFC registers 101 | /* 102 | { 0x50260, new[] { 103 | new TimingDef { Name = "", HiBit = 0, LoBit = 0 }, 104 | }}, 105 | { 0x50264, new[] { 106 | new TimingDef { Name = "", HiBit = 0, LoBit = 0 }, 107 | }}, 108 | */ 109 | }; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Dictionaries/DDR5Dictionary.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using static ZenStates.Core.DRAM.MemoryConfig; 3 | 4 | namespace ZenStates.Core 5 | { 6 | internal static class DDR5Dictionary 7 | { 8 | public static readonly Dictionary defs = new Dictionary 9 | { 10 | /* 11 | { 0x50050, new[] { 12 | new TimingDef { Name = "BGS0", HiBit = 31, LoBit = 0 }, 13 | }}, 14 | { 0x50058, new[] { 15 | new TimingDef { Name = "BGS1", HiBit = 31, LoBit = 0 }, 16 | }}, 17 | { 0x500D0, new[] { 18 | new TimingDef { Name = "BGSAlt0", HiBit = 10, LoBit = 4 }, 19 | }}, 20 | { 0x500D4, new[] { 21 | new TimingDef { Name = "BGSAlt1", HiBit = 10, LoBit = 4 }, 22 | }}, 23 | */ 24 | { 0x5012C, new[] { 25 | new TimingDef { Name = "PowerDown", HiBit = 28, LoBit = 28 }, 26 | }}, 27 | { 0x50200, new[] { 28 | new TimingDef { Name = "Cmd2T", HiBit = 17, LoBit = 17 }, 29 | new TimingDef { Name = "GDM", HiBit = 18, LoBit = 18 }, 30 | // new TimingDef { Name = "Ratio", HiBit = 15, LoBit = 0 }, 31 | }}, 32 | { 0x50204, new[] { 33 | new TimingDef { Name = "RCDWR", HiBit = 29 , LoBit = 24 }, 34 | new TimingDef { Name = "RCDRD", HiBit = 21 , LoBit = 16 }, 35 | new TimingDef { Name = "RAS", HiBit = 14 , LoBit = 8 }, 36 | new TimingDef { Name = "CL", HiBit = 5 , LoBit = 0 }, 37 | }}, 38 | { 0x50208, new[] { 39 | new TimingDef { Name = "RC", HiBit = 7 , LoBit = 0 }, 40 | new TimingDef { Name = "RP", HiBit = 21 , LoBit = 16 }, 41 | }}, 42 | { 0x5020C, new[] { 43 | new TimingDef { Name = "RTP", HiBit = 28 , LoBit = 24 }, 44 | new TimingDef { Name = "RRDL", HiBit = 12 , LoBit = 8 }, 45 | new TimingDef { Name = "RRDS", HiBit = 4 , LoBit = 0 }, 46 | }}, 47 | { 0x50210, new[] { 48 | new TimingDef { Name = "FAW", HiBit = 7 , LoBit = 0 }, 49 | }}, 50 | { 0x50214, new[] { 51 | new TimingDef { Name = "WTRL", HiBit = 22 , LoBit = 16 }, 52 | new TimingDef { Name = "WTRS", HiBit = 12 , LoBit = 8 }, 53 | new TimingDef { Name = "CWL", HiBit = 5 , LoBit = 0 }, 54 | }}, 55 | { 0x50218, new[] { 56 | new TimingDef { Name = "WR", HiBit = 7 , LoBit = 0 }, 57 | }}, 58 | { 0x5021C, new[] { 59 | new TimingDef { Name = "TRCPAGE", HiBit = 31 , LoBit = 20 }, // ? 60 | }}, 61 | { 0x50220, new[] { 62 | new TimingDef { Name = "RDRDSCL", HiBit = 29 , LoBit = 24 }, // ? 63 | new TimingDef { Name = "RDRDSC", HiBit = 19 , LoBit = 16 }, 64 | new TimingDef { Name = "RDRDSD", HiBit = 11 , LoBit = 8 }, 65 | new TimingDef { Name = "RDRDDD", HiBit = 3 , LoBit = 0 }, 66 | }}, 67 | { 0x50224, new[] { 68 | new TimingDef { Name = "WRWRSCL", HiBit = 29 , LoBit = 24 }, // ? 69 | new TimingDef { Name = "WRWRSC", HiBit = 19 , LoBit = 16 }, 70 | new TimingDef { Name = "WRWRSD", HiBit = 11 , LoBit = 8 }, 71 | new TimingDef { Name = "WRWRDD", HiBit = 3 , LoBit = 0 }, 72 | }}, 73 | { 0x50228, new[] { 74 | new TimingDef { Name = "RDWR", HiBit = 13 , LoBit = 8 }, 75 | new TimingDef { Name = "WRRD", HiBit = 3 , LoBit = 0 }, 76 | }}, 77 | { 0x50230, new[] { 78 | new TimingDef { Name = "REFI", HiBit = 15 , LoBit = 0 }, 79 | }}, 80 | { 0x50234, new[] { 81 | new TimingDef { Name = "MODPDA", HiBit = 29 , LoBit = 24 }, 82 | new TimingDef { Name = "MRDPDA", HiBit = 21 , LoBit = 16 }, 83 | new TimingDef { Name = "MOD", HiBit = 13 , LoBit = 8 }, 84 | new TimingDef { Name = "MRD", HiBit = 5 , LoBit = 0 }, 85 | }}, 86 | { 0x50250, new[] { 87 | new TimingDef { Name = "STAG", HiBit = 26 , LoBit = 16 }, 88 | }}, 89 | { 0x50254, new[] { 90 | new TimingDef { Name = "CKE", HiBit = 28 , LoBit = 24 }, 91 | new TimingDef { Name = "XP", HiBit = 5 , LoBit = 0 }, 92 | }}, 93 | { 0x50258, new[] { 94 | new TimingDef { Name = "PHYWRD", HiBit = 26 , LoBit = 24 }, 95 | new TimingDef { Name = "PHYRDL", HiBit = 23 , LoBit = 16 }, 96 | new TimingDef { Name = "PHYWRL", HiBit = 15 , LoBit = 8 }, 97 | }}, 98 | /* 99 | { 0x50284, new[] { 100 | new TimingDef { Name = "RxData", HiBit = 5 , LoBit = 4 }, 101 | new TimingDef { Name = "TxData", HiBit = 3 , LoBit = 2 }, 102 | new TimingDef { Name = "CtrlLine", HiBit = 1 , LoBit = 0 }, 103 | }}, 104 | // TRFC and TRFC2 regs, one should be != 0x00C00138 105 | { 0x50260, new[] { 106 | new TimingDef { Name = "RFC", HiBit = 15 , LoBit = 0 }, 107 | new TimingDef { Name = "RFC2", HiBit = 31 , LoBit = 16 }, 108 | }}, 109 | { 0x50264, new[] { 110 | new TimingDef { Name = "RFC", HiBit = 15 , LoBit = 0 }, 111 | new TimingDef { Name = "RFC2", HiBit = 31 , LoBit = 16 }, 112 | }}, 113 | { 0x50268, new[] { 114 | new TimingDef { Name = "RFC", HiBit = 15 , LoBit = 0 }, 115 | new TimingDef { Name = "RFC2", HiBit = 31 , LoBit = 16 }, 116 | }}, 117 | { 0x5026C, new[] { 118 | new TimingDef { Name = "RFC", HiBit = 15 , LoBit = 0 }, 119 | new TimingDef { Name = "RFC2", HiBit = 31 , LoBit = 16 }, 120 | }}, 121 | // RFCsb regs, one of them should be != 0 122 | { 0x502c0, new[] { 123 | new TimingDef { Name = "RFCsb", HiBit = 10 , LoBit = 0 }, 124 | }}, 125 | { 0x502c4, new[] { 126 | new TimingDef { Name = "RFCsb", HiBit = 10 , LoBit = 0 }, 127 | }}, 128 | { 0x502c8, new[] { 129 | new TimingDef { Name = "RFCsb", HiBit = 10 , LoBit = 0 }, 130 | }}, 131 | { 0x502cc, new[] { 132 | new TimingDef { Name = "RFCsb", HiBit = 10 , LoBit = 0 }, 133 | }}, 134 | */ 135 | }; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /External/InpOut/DLPortIO.txt: -------------------------------------------------------------------------------- 1 | From Verison 1.0.0.7, InpOut provides basic DLPortIO compatibility, for use with LCDSmartie etc. 2 | 3 | It is however, not fully tested as my development machines (DFI motherboard) does not have a parallel port!!! 4 | To use with LCD smartie, take the 32bit DLL (in \Win32) and rename it to DLPortIO.dll 5 | 6 | Copy this DLL to your LCD Smartie folder and then give LCDSmartie a go. 7 | I know that LCD Smartie loads the DLL and talks to it properly - I'm just unsure if it reads/writes the port. 8 | 9 | Let me know if you have any problems. 10 | 11 | Thanks, 12 | Phil (Phil@Highrez.co.uk) -------------------------------------------------------------------------------- /External/InpOut/ReadMe.txt: -------------------------------------------------------------------------------- 1 | InpOut32Drv Driver Interface DLL 2 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3 | 4 | Modified for x64 compatibility and built by Phillip Gibbons (Phil@highrez.co.uk). 5 | See http://www.highrez.co.uk/Downloads/InpOut32 or the Highrez Forums (http://forums.highrez.co.uk) for information. 6 | Many thanks to Red Fox UK for supporting the community and providing Driver signatures allowing Vista/7 x64 compatibility. 7 | 8 | 9 | 10 | Based on the original written by Logix4U (www.logix4u.net). 11 | 12 | 13 | Notes: 14 | 15 | The InpOut32 device driver supports writing to "old fashioned" hardware port addresses. 16 | It does NOT support USB devices such as USB Parallel ports or even PCI parallel ports (as I am lead to believe). 17 | 18 | 19 | The device driver is installed at runtime. To do this however needs administrator privileges. 20 | On Vista & later, using UAC, you can run the InstallDriver.exe in the \Win32 folder to install the driver 21 | appropriate for your OS. Doing so will request elevation and ask for your permission (or for the administrator 22 | password). Once the driver is installed for the first time, it can then be used by any user *without* 23 | administrator privileges 24 | 25 | -------------------------------------------------------------------------------- /External/InpOut/Win32/InstallDriver.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irusanov/ZenStates-Core/6ff1ac847d8c7410e4eef9a1bdbedc8d7ed1a7e4/External/InpOut/Win32/InstallDriver.exe -------------------------------------------------------------------------------- /External/InpOut/Win32/inpout32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irusanov/ZenStates-Core/6ff1ac847d8c7410e4eef9a1bdbedc8d7ed1a7e4/External/InpOut/Win32/inpout32.dll -------------------------------------------------------------------------------- /External/InpOut/Win32/inpout32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //Functions exported from DLL. 4 | //For easy inclusion is user projects. 5 | //Original InpOut32 function support 6 | void _stdcall Out32(short PortAddress, short data); 7 | short _stdcall Inp32(short PortAddress); 8 | 9 | //My extra functions for making life easy 10 | BOOL _stdcall IsInpOutDriverOpen(); //Returns TRUE if the InpOut driver was opened successfully 11 | BOOL _stdcall IsXP64Bit(); //Returns TRUE if the OS is 64bit (x64) Windows. 12 | 13 | //DLLPortIO function support 14 | UCHAR _stdcall DlPortReadPortUchar (USHORT port); 15 | void _stdcall DlPortWritePortUchar(USHORT port, UCHAR Value); 16 | 17 | USHORT _stdcall DlPortReadPortUshort (USHORT port); 18 | void _stdcall DlPortWritePortUshort(USHORT port, USHORT Value); 19 | 20 | ULONG _stdcall DlPortReadPortUlong(ULONG port); 21 | void _stdcall DlPortWritePortUlong(ULONG port, ULONG Value); 22 | 23 | //WinIO function support (Untested and probably does NOT work - esp. on x64!) 24 | PBYTE _stdcall MapPhysToLin(PBYTE pbPhysAddr, DWORD dwPhysSize, HANDLE *pPhysicalMemoryHandle); 25 | BOOL _stdcall UnmapPhysicalMemory(HANDLE PhysicalMemoryHandle, PBYTE pbLinAddr); 26 | BOOL _stdcall GetPhysLong(PBYTE pbPhysAddr, PDWORD pdwPhysVal); 27 | BOOL _stdcall SetPhysLong(PBYTE pbPhysAddr, DWORD dwPhysVal); 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /External/InpOut/Win32/inpout32.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irusanov/ZenStates-Core/6ff1ac847d8c7410e4eef9a1bdbedc8d7ed1a7e4/External/InpOut/Win32/inpout32.lib -------------------------------------------------------------------------------- /External/InpOut/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) <2003-2015> Phil Gibbons 2 | Portions Copyright (c) <2000> 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. -------------------------------------------------------------------------------- /External/WinIo/LICENSE.txt: -------------------------------------------------------------------------------- 1 | END USER LICENSE AGREEMENT 2 | 3 | Software License Agreement for WinIo 4 | The following terms apply to all files associated with the software unless 5 | explicitly disclaimed in individual files. 6 | 7 | IMPORTANT- PLEASE READ CAREFULLY: BY INSTALLING THE SOFTWARE (AS DEFINED BELOW), 8 | OR COPYING THE SOFTWARE, YOU (EITHER ON BEHALF OF YOURSELF AS AN INDIVIDUAL OR 9 | ON BEHALF OF AN ENTITY AS ITS AUTHORIZED REPRESENTATIVE) AGREE TO ALL OF THE 10 | TERMS OF THIS END USER LICENSE AGREEMENT ("AGREEMENT") REGARDING YOUR USE OF 11 | THE SOFTWARE. IF YOU DO NOT AGREE WITH ALL OF THE TERMS OF THIS AGREEMENT, DO 12 | NOT INSTALL, COPY OR OTHERWISE USE THE SOFTWARE. 13 | 14 | 1. GRANT OF LICENSE: Subject to the terms below, Yariv Kaplan ("AUTHOR") hereby 15 | grants you a non-exclusive, non-transferable, non-assignable license to install 16 | and to use the downloadable version of WinIo ("SOFTWARE"). 17 | 18 | a. Redistributable Code. You may reproduce and distribute the object code form 19 | of the SOFTWARE solely in conjunction with, and as part of, your application 20 | ("Permitted Application"); provided that you comply with the following: 21 | 22 | If you redistribute any portion of the Redistributable Code, you agree that: 23 | 24 | (i) you will only distribute the Redistributable Code in conjunction with, and 25 | as part of, your Permitted Application which adds significant functionality to 26 | the Redistributable Code and that distribution of the Permitted Application does 27 | not compete with the AUTHOR's distribution of the SOFTWARE; 28 | 29 | (ii) you will include a valid copyright notice on your Permitted Application; 30 | 31 | (iii) you will not permit further redistribution of the Redistributable Code; 32 | 33 | (iv) you will indemnify, hold harmless, and defend the AUTHOR from and against 34 | any claims or lawsuits, including attorneys' fees, that arise or result from 35 | the use or distribution of your Permitted Application. 36 | 37 | b. License to use Source Code. You may not sell, lease, rent, transfer or 38 | sublicense the source code of this SOFTWARE. 39 | 40 | 2. MODIFICATION: SOFTWARE Source Code may be modified without the prior written 41 | permission of the AUTHOR. Any modifications made to the SOFTWARE will continue 42 | to be subject to the terms and conditions of this AGREEMENT. 43 | 44 | 3. COPYRIGHT: All rights, title, and copyrights in and to the SOFTWARE and any 45 | copies of the SOFTWARE are owned by the AUTHOR. The SOFTWARE is protected by 46 | copyright laws and international treaty provisions. Therefore, you must treat 47 | the SOFTWARE like any other copyrighted material. 48 | 49 | 4. TITLE: You acknowledge that no title to the intellectual property in the 50 | SOFTWARE is transferred to you. Title, ownership, rights, and intellectual 51 | property rights in and to the SOFTWARE shall remain the exclusive property of 52 | the AUTHOR. The SOFTWARE is protected by copyright laws of the United States 53 | and international treaties. 54 | 55 | 5. LIMITATION OF LIABILITY: You must assume the entire risk of using the 56 | SOFTWARE. 57 | 58 | IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 59 | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS 60 | SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHOR 61 | HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 | 63 | THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED 64 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 65 | PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, 66 | AND THE AUTHOR HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 67 | ENHANCEMENTS, OR MODIFICATIONS. -------------------------------------------------------------------------------- /External/WinIo/WinIo32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irusanov/ZenStates-Core/6ff1ac847d8c7410e4eef9a1bdbedc8d7ed1a7e4/External/WinIo/WinIo32.dll -------------------------------------------------------------------------------- /External/WinIo/WinIo32.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irusanov/ZenStates-Core/6ff1ac847d8c7410e4eef9a1bdbedc8d7ed1a7e4/External/WinIo/WinIo32.sys -------------------------------------------------------------------------------- /External/WinRing0/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007-2009 OpenLibSys.org. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 13 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 14 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 15 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 16 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 17 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 18 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 19 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /External/WinRing0/WinRing0.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irusanov/ZenStates-Core/6ff1ac847d8c7410e4eef9a1bdbedc8d7ed1a7e4/External/WinRing0/WinRing0.sys -------------------------------------------------------------------------------- /External/WinRing0/WinRing0x64.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irusanov/ZenStates-Core/6ff1ac847d8c7410e4eef9a1bdbedc8d7ed1a7e4/External/WinRing0/WinRing0x64.sys -------------------------------------------------------------------------------- /IOModule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Management; 6 | using System.Runtime.InteropServices; 7 | using System.Security.AccessControl; 8 | using System.ServiceProcess; 9 | 10 | namespace ZenStates.Core 11 | { 12 | public sealed class IOModule : IDisposable 13 | { 14 | [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)] 15 | private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName); 16 | 17 | [DllImport("kernel32", SetLastError = true)] 18 | private static extern bool FreeLibrary(IntPtr hModule); 19 | 20 | [DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = false)] 21 | private static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName); 22 | 23 | internal IntPtr ioModule; 24 | 25 | public enum LibStatus 26 | { 27 | INITIALIZE_ERROR = 0, 28 | OK = 1, 29 | PARTIALLY_OK = 2 30 | } 31 | 32 | private LibStatus WinIoStatus { get; } = LibStatus.INITIALIZE_ERROR; 33 | 34 | public bool IsInpOutDriverOpen() 35 | { 36 | if (Utils.Is64Bit) 37 | return IsInpOutDriverOpen64() != 0; 38 | else 39 | return WinIoStatus == LibStatus.OK; 40 | } 41 | 42 | public byte[] ReadMemory(IntPtr baseAddress, int size) 43 | { 44 | try 45 | { 46 | if (MapPhysToLin != null && UnmapPhysicalMemory != null) 47 | { 48 | IntPtr pdwLinAddr = MapPhysToLin(baseAddress, (uint)size, out IntPtr pPhysicalMemoryHandle); 49 | if (pdwLinAddr != IntPtr.Zero) 50 | { 51 | byte[] bytes = new byte[size]; 52 | Marshal.Copy(pdwLinAddr, bytes, 0, bytes.Length); 53 | UnmapPhysicalMemory(pPhysicalMemoryHandle, pdwLinAddr); 54 | 55 | return bytes; 56 | } 57 | } 58 | } 59 | catch (Exception ex) 60 | { 61 | Console.WriteLine($"Error reading memory: {ex.Message}"); 62 | } 63 | 64 | return null; 65 | } 66 | 67 | public static IntPtr LoadDll(string filename) 68 | { 69 | IntPtr dll = LoadLibrary(filename); 70 | 71 | if (dll == IntPtr.Zero) 72 | { 73 | int lasterror = Marshal.GetLastWin32Error(); 74 | Win32Exception innerEx = new Win32Exception(lasterror); 75 | innerEx.Data.Add("LastWin32Error", lasterror); 76 | 77 | throw new Exception("Can't load DLL " + filename, innerEx); 78 | } 79 | 80 | return dll; 81 | } 82 | 83 | public IOModule() 84 | { 85 | try 86 | { 87 | // restrict the driver access to system (SY) and builtin admins (BA) 88 | // TODO: replace with a call to IoCreateDeviceSecure in the driver 89 | string filePath = @"\\.\inpoutx64"; 90 | FileInfo fileInfo = new FileInfo(filePath); 91 | FileSecurity fileSecurity = fileInfo.GetAccessControl(); 92 | fileSecurity.SetSecurityDescriptorSddlForm("O:BAG:SYD:(A;;FA;;;SY)(A;;FA;;;BA)"); 93 | fileInfo.SetAccessControl(fileSecurity); 94 | } 95 | catch { } 96 | 97 | try 98 | { 99 | string fileName = Utils.Is64Bit ? "inpoutx64.dll" : "WinIo32.dll"; 100 | ioModule = LoadDll(fileName); 101 | 102 | // Common 103 | GetPhysLong = (_GetPhysLong)GetDelegate(ioModule, "GetPhysLong", typeof(_GetPhysLong)); 104 | SetPhysLong = (_SetPhysLong)GetDelegate(ioModule, "SetPhysLong", typeof(_SetPhysLong)); 105 | MapPhysToLin = (_MapPhysToLin)GetDelegate(ioModule, "MapPhysToLin", typeof(_MapPhysToLin)); 106 | UnmapPhysicalMemory = (_UnmapPhysicalMemory)GetDelegate(ioModule, "UnmapPhysicalMemory", typeof(_UnmapPhysicalMemory)); 107 | 108 | // 64bit only 109 | if (Utils.Is64Bit) 110 | { 111 | IsInpOutDriverOpen64 = (_IsInpOutDriverOpen64)GetDelegate(ioModule, "IsInpOutDriverOpen", typeof(_IsInpOutDriverOpen64)); 112 | } 113 | else 114 | { 115 | InitializeWinIo32 = (_InitializeWinIo32)GetDelegate(ioModule, "InitializeWinIo", typeof(_InitializeWinIo32)); 116 | ShutdownWinIo32 = (_ShutdownWinIo32)GetDelegate(ioModule, "ShutdownWinIo", typeof(_ShutdownWinIo32)); 117 | 118 | if (InitializeWinIo32()) 119 | { 120 | WinIoStatus = LibStatus.OK; 121 | } 122 | } 123 | } 124 | catch (Exception ex) 125 | { 126 | throw new Exception($"Error initializing IO module: {ex.Message}"); 127 | } 128 | } 129 | 130 | public delegate bool _GetPhysLong(UIntPtr memAddress, out uint data); 131 | public readonly _GetPhysLong GetPhysLong; 132 | 133 | public delegate bool _SetPhysLong(UIntPtr memAddress, uint data); 134 | public readonly _SetPhysLong SetPhysLong; 135 | 136 | private delegate IntPtr _MapPhysToLin(IntPtr pbPhysAddr, uint dwPhysSize, out IntPtr pPhysicalMemoryHandle); 137 | private readonly _MapPhysToLin MapPhysToLin; 138 | 139 | private delegate bool _UnmapPhysicalMemory(IntPtr PhysicalMemoryHandle, IntPtr pbLinAddr); 140 | private readonly _UnmapPhysicalMemory UnmapPhysicalMemory; 141 | 142 | // InpOutx64 143 | private delegate uint _IsInpOutDriverOpen64(); 144 | private readonly _IsInpOutDriverOpen64 IsInpOutDriverOpen64; 145 | 146 | // WinIo 147 | private delegate bool _InitializeWinIo32(); 148 | private delegate bool _ShutdownWinIo32(); 149 | private readonly _InitializeWinIo32 InitializeWinIo32; 150 | private readonly _ShutdownWinIo32 ShutdownWinIo32; 151 | 152 | private void CleanupDriver() 153 | { 154 | if (IsInpOutDriverOpen()) 155 | return; 156 | 157 | string serviceName = "inpoutx64"; 158 | string registryKeyPath = @"SYSTEM\CurrentControlSet\Services\" + serviceName; 159 | string driverFilePath = $@"C:\Windows\System32\drivers\{serviceName}.sys"; 160 | 161 | try 162 | { 163 | // Stop the service 164 | using (ServiceController serviceController = new ServiceController(serviceName)) 165 | { 166 | if (serviceController.Status == ServiceControllerStatus.Running) 167 | { 168 | serviceController.Stop(); 169 | serviceController.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(10000)); 170 | Console.WriteLine("Service stopped successfully."); 171 | } 172 | 173 | if (serviceController.Status != ServiceControllerStatus.Stopped) 174 | { 175 | 176 | Console.WriteLine("Failed to stop the service."); 177 | return; 178 | } 179 | } 180 | 181 | // Delete the service 182 | using (ManagementObject service = new ManagementObject($"Win32_Service.Name='{serviceName}'")) 183 | { 184 | service.Delete(); 185 | Console.WriteLine("Service deleted successfully."); 186 | } 187 | 188 | 189 | // Remove the registry key using the regedit command-line tool 190 | Process regeditProcess = new Process(); 191 | regeditProcess.StartInfo.FileName = "regedit"; 192 | regeditProcess.StartInfo.Arguments = $"/s /f \"{registryKeyPath}\""; 193 | regeditProcess.StartInfo.UseShellExecute = false; 194 | regeditProcess.Start(); 195 | 196 | regeditProcess.WaitForExit(); 197 | 198 | if (regeditProcess.ExitCode == 0) 199 | { 200 | Console.WriteLine("Registry key removed successfully."); 201 | } 202 | else 203 | { 204 | Console.WriteLine("Failed to remove the registry key."); 205 | } 206 | 207 | // Delete the driver file 208 | if (File.Exists(driverFilePath)) 209 | { 210 | File.Delete(driverFilePath); 211 | Console.WriteLine("Driver file deleted successfully."); 212 | } 213 | else 214 | { 215 | Console.WriteLine("Driver file does not exist."); 216 | } 217 | 218 | Console.WriteLine("Process completed."); 219 | Console.ReadLine(); 220 | } 221 | catch (Exception ex) 222 | { 223 | Console.WriteLine("An error occurred:"); 224 | Console.WriteLine(ex.Message); 225 | } 226 | } 227 | 228 | public void Dispose() 229 | { 230 | if (ioModule == IntPtr.Zero) return; 231 | if (!Utils.Is64Bit) 232 | ShutdownWinIo32(); 233 | 234 | FreeLibrary(ioModule); 235 | ioModule = IntPtr.Zero; 236 | 237 | //if (Utils.Is64Bit) 238 | // CleanupDriver(); 239 | } 240 | 241 | public static Delegate GetDelegate(IntPtr moduleName, string procName, Type delegateType) 242 | { 243 | IntPtr ptr = GetProcAddress(moduleName, procName); 244 | if (ptr != IntPtr.Zero) 245 | { 246 | Delegate d = Marshal.GetDelegateForFunctionPointer(ptr, delegateType); 247 | return d; 248 | } 249 | 250 | int result = Marshal.GetHRForLastWin32Error(); 251 | throw Marshal.GetExceptionForHR(result); 252 | } 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /Mailbox/HSMPMailbox.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core 2 | { 3 | // HSMP 4 | // Processor Programming Reference (PPR) for Family 19h Model 01h, Revision B1 Processors, vol 2 5 | // https://www.amd.com/system/files/TechDocs/55898_pub.zip 6 | // Interface Version Supported Function IDs 7 | // 0001h 01h through 11h 8 | // 0002h 01h through 12h 9 | // 0003h 01h through 14h 10 | // 0004h 01h through 15h 11 | // 0005h 01h through 22h 12 | public sealed class HSMPMailbox : Mailbox 13 | { 14 | public uint InterfaceVersion; 15 | public uint HighestSupportedFunction; 16 | public HSMPMailbox(uint maxArgs = Constants.HSMP_MAILBOX_ARGS) : base(maxArgs) { } 17 | 18 | private uint GetHighestSupportedId() 19 | { 20 | switch (InterfaceVersion) 21 | { 22 | case 1: 23 | return 0x11; 24 | case 2: 25 | return 0x12; 26 | case 3: 27 | return 0x14; 28 | case 4: 29 | return 0x15; 30 | case 5: 31 | return 0x2F; 32 | case 7: 33 | return 0x3F; 34 | default: 35 | return 0x3F; 36 | } 37 | } 38 | 39 | public void Init(Cpu cpu) 40 | { 41 | if (cpu.smu != null) 42 | { 43 | uint[] args = Utils.MakeCmdArgs(0, this.MAX_ARGS); 44 | // SendSmuCommand would not execute if mailbox addresses are not defined 45 | if (cpu.smu.SendSmuCommand(this, this.GetInterfaceVersion, ref args) == SMU.Status.OK) 46 | { 47 | this.InterfaceVersion = args[0]; 48 | this.HighestSupportedFunction = GetHighestSupportedId(); 49 | } 50 | } 51 | } 52 | 53 | public bool IsSupported => InterfaceVersion > 0; 54 | public uint GetInterfaceVersion { get; set; } = 0x3; 55 | public uint ReadSocketPower { get; set; } = 0x4; 56 | public uint WriteSocketPowerLimit { get; set; } = 0x5; 57 | public uint ReadSocketPowerLimit { get; set; } = 0x6; 58 | public uint ReadMaxSocketPowerLimit { get; set; } = 0x7; 59 | public uint WriteBoostLimit { get; set; } = 0x8; 60 | public uint WriteBoostLimitAllCores { get; set; } = 0x9; 61 | public uint ReadBoostLimit { get; set; } = 0xA; 62 | public uint ReadProchotStatus { get; set; } = 0xB; 63 | public uint SetXgmiLinkWidthRange { get; set; } = 0xC; 64 | public uint APBDisable { get; set; } = 0xD; 65 | public uint APBEnable { get; set; } = 0xE; 66 | public uint ReadCurrentFclkMemclk { get; set; } = 0xF; 67 | public uint ReadCclkFrequencyLimit { get; set; } = 0x10; 68 | public uint ReadSocketC0Residency { get; set; } = 0x11; 69 | public uint SetLclkDpmLevelRange { get; set; } = 0x12; 70 | public uint GetLclkDpmLevelRange { get; set; } = 0x13; 71 | public uint GetMaxDDRBandwidthAndUtilization { get; set; } = 0x14; 72 | // Reserved = 0x15 73 | public uint GetDIMMTempRangeAndRefreshRate { get; set; } = 0x16; 74 | public uint GetDIMMPowerConsumption { get; set; } = 0x17; 75 | public uint GetDIMMThermalSensor { get; set; } = 0x18; 76 | public uint PwrCurrentActiveFreqLimitSocket { get; set; } = 0x19; 77 | public uint PwrCurrentActiveFreqLimitCore { get; set; } = 0x1A; 78 | public uint PwrSviTelemetryAllRails { get; set; } = 0x1B; 79 | public uint GetSocketFreqRange { get; set; } = 0x1C; 80 | public uint GetCurrentIoBandwidth { get; set; } = 0x1D; 81 | public uint GetCurrentXgmiBandwidth { get; set; } = 0xE; 82 | public uint SetGMI3LinkWidthRange { get; set; } = 0x1F; 83 | public uint ControlPcieLinkRate { get; set; } = 0x20; 84 | public uint PwrEfficiencyModeSelection { get; set; } = 0x21; 85 | public uint SetDfPstateRange { get; set; } = 0x22; 86 | // Reserved = 0x23 87 | // Reserved = 0x24 88 | // Reserved = 0x25 89 | public uint XgmiPstateRange { get; set; } = 0x26; 90 | public uint CpuRailIsoFreqPolicy { get; set; } = 0x27; 91 | public uint DfcEnable { get; set; } = 0x28; 92 | // 29h-2Fh Reserved 93 | public uint GetRaplUnits { get; set; } = 0x30; 94 | public uint GetRaplCoreCounter { get; set; } = 0x31; 95 | public uint GetRaplPackageCounter { get; set; } = 0x32; 96 | } 97 | } -------------------------------------------------------------------------------- /Mailbox/MP1Mailbox.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core 2 | { 3 | public sealed class MP1Mailbox : Mailbox 4 | { 5 | // Configurable commands 6 | public uint SMU_MSG_SetToolsDramAddress { get; set; } = 0x0; 7 | public uint SMU_MSG_EnableOcMode { get; set; } = 0x0; 8 | public uint SMU_MSG_DisableOcMode { get; set; } = 0x0; 9 | public uint SMU_MSG_SetOverclockFrequencyAllCores { get; set; } = 0x0; 10 | public uint SMU_MSG_SetOverclockFrequencyPerCore { get; set; } = 0x0; 11 | public uint SMU_MSG_SetBoostLimitFrequencyAllCores { get; set; } = 0x0; 12 | public uint SMU_MSG_SetBoostLimitFrequency { get; set; } = 0x0; 13 | public uint SMU_MSG_SetOverclockCpuVid { get; set; } = 0x0; 14 | public uint SMU_MSG_SetDldoPsmMargin { get; set; } = 0x0; 15 | public uint SMU_MSG_SetAllDldoPsmMargin { get; set; } = 0x0; 16 | public uint SMU_MSG_GetDldoPsmMargin { get; set; } = 0x0; 17 | public uint SMU_MSG_SetPBOScalar { get; set; } = 0x0; 18 | public uint SMU_MSG_SetEDCVDDLimit { get; set; } = 0x0; 19 | public uint SMU_MSG_SetTDCVDDLimit { get; set; } = 0x0; 20 | public uint SMU_MSG_SetPPTLimit { get; set; } = 0x0; 21 | public uint SMU_MSG_SetHTCLimit { get; set; } = 0x0; 22 | } 23 | } -------------------------------------------------------------------------------- /Mailbox/Mailbox.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core 2 | { 3 | public class Mailbox 4 | { 5 | public Mailbox(uint maxArgs = Constants.DEFAULT_MAILBOX_ARGS) 6 | { 7 | this.MAX_ARGS = maxArgs; 8 | } 9 | public uint MAX_ARGS { get; protected set; } 10 | // Configurable registers 11 | public uint SMU_ADDR_MSG { get; set; } = 0x0; 12 | public uint SMU_ADDR_RSP { get; set; } = 0x0; 13 | public uint SMU_ADDR_ARG { get; set; } = 0x0; 14 | // SMU Messages (command IDs) 15 | // 0x1 and 0x2 seem to be common for all mailboxes 16 | public uint SMU_MSG_TestMessage { get; } = 0x1; 17 | public uint SMU_MSG_GetSmuVersion { get; } = 0x2; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Mailbox/RSMUMailbox.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core 2 | { 3 | public sealed class RSMUMailbox : Mailbox 4 | { 5 | // Configurable commands 6 | public uint SMU_MSG_GetTableVersion { get; set; } = 0x0; 7 | public uint SMU_MSG_GetBiosIfVersion { get; set; } = 0x0; 8 | public uint SMU_MSG_TransferTableToDram { get; set; } = 0x0; 9 | public uint SMU_MSG_GetDramBaseAddress { get; set; } = 0x0; 10 | public uint SMU_MSG_EnableSmuFeatures { get; set; } = 0x0; 11 | public uint SMU_MSG_DisableSmuFeatures { get; set; } = 0x0; 12 | public uint SMU_MSG_SetOverclockFrequencyAllCores { get; set; } = 0x0; 13 | public uint SMU_MSG_SetOverclockFrequencyPerCore { get; set; } = 0x0; 14 | public uint SMU_MSG_SetBoostLimitFrequencyAllCores { get; set; } = 0x0; 15 | public uint SMU_MSG_GetBoostLimitFrequency { get; set; } = 0x0; 16 | public uint SMU_MSG_SetBoostLimitFrequency { get; set; } = 0x0; 17 | public uint SMU_MSG_SetOverclockCpuVid { get; set; } = 0x0; 18 | public uint SMU_MSG_EnableOcMode { get; set; } = 0x0; 19 | public uint SMU_MSG_DisableOcMode { get; set; } = 0x0; 20 | public uint SMU_MSG_GetPBOScalar { get; set; } = 0x0; 21 | public uint SMU_MSG_SetPBOScalar { get; set; } = 0x0; 22 | public uint SMU_MSG_SetPPTLimit { get; set; } = 0x0; 23 | public uint SMU_MSG_SetTDCVDDLimit { get; set; } = 0x0; 24 | public uint SMU_MSG_SetTDCSOCLimit { get; set; } = 0x0; 25 | public uint SMU_MSG_SetEDCVDDLimit { get; set; } = 0x0; 26 | public uint SMU_MSG_SetEDCSOCLimit { get; set; } = 0x0; 27 | public uint SMU_MSG_SetHTCLimit { get; set; } = 0x0; 28 | public uint SMU_MSG_GetTjMax { get; set; } = 0x0; 29 | public uint SMU_MSG_SetTjMax { get; set; } = 0x0; 30 | public uint SMU_MSG_PBO_EN { get; set; } = 0x0; 31 | public uint SMU_MSG_SetDldoPsmMargin { get; set; } = 0x0; 32 | public uint SMU_MSG_SetAllDldoPsmMargin { get; set; } = 0x0; 33 | public uint SMU_MSG_GetDldoPsmMargin { get; set; } = 0x0; 34 | public uint SMU_MSG_SetGpuPsmMargin { get; set; } = 0x0; 35 | public uint SMU_MSG_GetGpuPsmMargin { get; set; } = 0x0; 36 | public uint SMU_MSG_ReadBoostLimit { get; set; } = 0x0; 37 | public uint SMU_MSG_GetFastestCoreofSocket { get; set; } = 0x0; 38 | public uint SMU_MSG_GetLN2Mode { get; set; } = 0x0; 39 | public uint SMU_MSG_IsOverclockable { get; set; } = 0x0; 40 | public uint SMU_MSG_GetPerformanceData { get; set; } = 0x0; 41 | } 42 | } -------------------------------------------------------------------------------- /OHWM/FirmwareTable.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This Source Code Form is subject to the terms of the Mozilla Public 4 | License, v. 2.0. If a copy of the MPL was not distributed with this 5 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | 7 | Copyright (C) 2011 Michael Möller 8 | 9 | */ 10 | 11 | using System; 12 | using System.Runtime.InteropServices; 13 | using System.Text; 14 | 15 | namespace OpenHardwareMonitor.Hardware 16 | { 17 | 18 | internal static class FirmwareTable 19 | { 20 | 21 | public static byte[] GetTable(Provider provider, string table) 22 | { 23 | int id = table[3] << 24 | table[2] << 16 | table[1] << 8 | table[0]; 24 | return GetTable(provider, id); 25 | } 26 | 27 | public static byte[] GetTable(Provider provider, int table) 28 | { 29 | 30 | int size; 31 | try 32 | { 33 | size = NativeMethods.GetSystemFirmwareTable(provider, table, 34 | IntPtr.Zero, 0); 35 | } 36 | catch (DllNotFoundException) { return null; } 37 | catch (EntryPointNotFoundException) { return null; } 38 | 39 | if (size <= 0) 40 | return null; 41 | 42 | IntPtr nativeBuffer = Marshal.AllocHGlobal(size); 43 | NativeMethods.GetSystemFirmwareTable(provider, table, nativeBuffer, size); 44 | 45 | if (Marshal.GetLastWin32Error() != 0) 46 | return null; 47 | 48 | byte[] buffer = new byte[size]; 49 | Marshal.Copy(nativeBuffer, buffer, 0, size); 50 | Marshal.FreeHGlobal(nativeBuffer); 51 | 52 | return buffer; 53 | } 54 | 55 | public static string[] EnumerateTables(Provider provider) 56 | { 57 | int size; 58 | try 59 | { 60 | size = NativeMethods.EnumSystemFirmwareTables( 61 | provider, IntPtr.Zero, 0); 62 | } 63 | catch (DllNotFoundException) { return null; } 64 | catch (EntryPointNotFoundException) { return null; } 65 | 66 | IntPtr nativeBuffer = Marshal.AllocHGlobal(size); 67 | NativeMethods.EnumSystemFirmwareTables( 68 | provider, nativeBuffer, size); 69 | byte[] buffer = new byte[size]; 70 | Marshal.Copy(nativeBuffer, buffer, 0, size); 71 | Marshal.FreeHGlobal(nativeBuffer); 72 | 73 | string[] result = new string[size / 4]; 74 | for (int i = 0; i < result.Length; i++) 75 | result[i] = Encoding.ASCII.GetString(buffer, 4 * i, 4); 76 | 77 | return result; 78 | } 79 | 80 | public enum Provider : int 81 | { 82 | ACPI = (byte)'A' << 24 | (byte)'C' << 16 | (byte)'P' << 8 | (byte)'I', 83 | FIRM = (byte)'F' << 24 | (byte)'I' << 16 | (byte)'R' << 8 | (byte)'M', 84 | RSMB = (byte)'R' << 24 | (byte)'S' << 16 | (byte)'M' << 8 | (byte)'B', 85 | } 86 | 87 | private static class NativeMethods 88 | { 89 | private const string KERNEL = "kernel32.dll"; 90 | 91 | [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi, 92 | SetLastError = true)] 93 | public static extern int EnumSystemFirmwareTables( 94 | Provider firmwareTableProviderSignature, 95 | IntPtr firmwareTableBuffer, int bufferSize); 96 | 97 | [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi, 98 | SetLastError = true)] 99 | public static extern int GetSystemFirmwareTable( 100 | Provider firmwareTableProviderSignature, 101 | int firmwareTableID, IntPtr firmwareTableBuffer, int bufferSize); 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /OHWM/GroupAffinity.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This Source Code Form is subject to the terms of the Mozilla Public 4 | License, v. 2.0. If a copy of the MPL was not distributed with this 5 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | 7 | Copyright (C) 2020 Michael Möller 8 | 9 | */ 10 | 11 | namespace OpenHardwareMonitor.Hardware 12 | { 13 | 14 | /// 15 | /// This structure describes a group-specific affinity. 16 | /// 17 | internal struct GroupAffinity 18 | { 19 | 20 | public static GroupAffinity Undefined = 21 | new GroupAffinity(ushort.MaxValue, 0); 22 | 23 | public GroupAffinity(ushort group, ulong mask) 24 | { 25 | this.Group = group; 26 | this.Mask = mask; 27 | } 28 | 29 | public static GroupAffinity Single(ushort group, int index) 30 | { 31 | return new GroupAffinity(group, 1UL << index); 32 | } 33 | 34 | public ushort Group { get; } 35 | 36 | public ulong Mask { get; } 37 | 38 | public override bool Equals(object o) 39 | { 40 | if (o == null || GetType() != o.GetType()) return false; 41 | GroupAffinity a = (GroupAffinity)o; 42 | return (Group == a.Group) && (Mask == a.Mask); 43 | } 44 | 45 | public override int GetHashCode() 46 | { 47 | return Group.GetHashCode() ^ Mask.GetHashCode(); 48 | } 49 | 50 | public static bool operator ==(GroupAffinity a1, GroupAffinity a2) 51 | { 52 | return (a1.Group == a2.Group) && (a1.Mask == a2.Mask); 53 | } 54 | 55 | public static bool operator !=(GroupAffinity a1, GroupAffinity a2) 56 | { 57 | return (a1.Group != a2.Group) || (a1.Mask != a2.Mask); 58 | } 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /OHWM/IOControlCode.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This Source Code Form is subject to the terms of the Mozilla Public 4 | License, v. 2.0. If a copy of the MPL was not distributed with this 5 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | 7 | Copyright (C) 2010 Michael Möller 8 | 9 | */ 10 | 11 | using System.Runtime.InteropServices; 12 | 13 | namespace OpenHardwareMonitor.Hardware 14 | { 15 | 16 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 17 | internal struct IOControlCode 18 | { 19 | private readonly uint code; 20 | 21 | public IOControlCode(uint deviceType, uint function, Access access) : 22 | this(deviceType, function, Method.Buffered, access) 23 | { } 24 | 25 | public IOControlCode(uint deviceType, uint function, Method method, 26 | Access access) 27 | { 28 | code = (deviceType << 16) | 29 | ((uint)access << 14) | (function << 2) | (uint)method; 30 | } 31 | 32 | public enum Method : uint 33 | { 34 | Buffered = 0, 35 | InDirect = 1, 36 | OutDirect = 2, 37 | Neither = 3 38 | } 39 | 40 | public enum Access : uint 41 | { 42 | Any = 0, 43 | Read = 1, 44 | Write = 2 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /OHWM/InteropMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace ZenStates.Core 5 | { 6 | // this class just wraps some Win32 stuff that we're going to use 7 | public static class InteropMethods 8 | { 9 | public const int HWND_BROADCAST = 0xffff; 10 | public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME"); 11 | 12 | public enum Provider : int 13 | { 14 | ACPI = (byte)'A' << 24 | (byte)'C' << 16 | (byte)'P' << 8 | (byte)'I', 15 | FIRM = (byte)'F' << 24 | (byte)'I' << 16 | (byte)'R' << 8 | (byte)'M', 16 | RSMB = (byte)'R' << 24 | (byte)'S' << 16 | (byte)'M' << 8 | (byte)'B', 17 | } 18 | 19 | [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 20 | [return: MarshalAs(UnmanagedType.Bool)] 21 | public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam); 22 | 23 | [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 24 | public static extern int RegisterWindowMessage(string lpString); 25 | 26 | [DllImport("psapi.dll")] 27 | public static extern int EmptyWorkingSet(IntPtr hwProc); 28 | 29 | // returns table size or 0 on error 30 | [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)] 31 | public static extern uint GetSystemFirmwareTable( 32 | Provider FirmwareTableProviderSignature, 33 | uint FirmwareTableID, 34 | [MarshalAs(UnmanagedType.LPArray), Out] byte[] pFirmwareTableBuffer, 35 | uint BufferSize); 36 | } 37 | } -------------------------------------------------------------------------------- /OHWM/KernelDriver.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This Source Code Form is subject to the terms of the Mozilla Public 4 | License, v. 2.0. If a copy of the MPL was not distributed with this 5 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | 7 | Copyright (C) 2010-2012 Michael Möller 8 | 9 | */ 10 | 11 | using Microsoft.Win32.SafeHandles; 12 | using System; 13 | using System.IO; 14 | using System.Runtime.InteropServices; 15 | using System.Security.AccessControl; 16 | 17 | namespace OpenHardwareMonitor.Hardware 18 | { 19 | internal class KernelDriver 20 | { 21 | 22 | private string id; 23 | 24 | private SafeFileHandle device; 25 | 26 | public KernelDriver(string id) 27 | { 28 | this.id = id; 29 | } 30 | 31 | public bool Install(string path, out string errorMessage) 32 | { 33 | IntPtr manager = NativeMethods.OpenSCManager(null, null, 34 | ServiceControlManagerAccessRights.SC_MANAGER_ALL_ACCESS); 35 | 36 | if (manager == IntPtr.Zero) 37 | { 38 | errorMessage = "OpenSCManager returned zero."; 39 | return false; 40 | } 41 | 42 | IntPtr service = NativeMethods.CreateService(manager, id, id, 43 | ServiceAccessRights.SERVICE_ALL_ACCESS, 44 | ServiceType.SERVICE_KERNEL_DRIVER, StartType.SERVICE_DEMAND_START, 45 | ErrorControl.SERVICE_ERROR_NORMAL, path, null, null, null, null, 46 | null); 47 | 48 | if (service == IntPtr.Zero) 49 | { 50 | if (Marshal.GetHRForLastWin32Error() == ERROR_SERVICE_EXISTS) 51 | { 52 | errorMessage = "Service already exists"; 53 | return false; 54 | } 55 | else 56 | { 57 | errorMessage = "CreateService returned the error: " + 58 | Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()).Message; 59 | NativeMethods.CloseServiceHandle(manager); 60 | return false; 61 | } 62 | } 63 | 64 | if (!NativeMethods.StartService(service, 0, null)) 65 | { 66 | if (Marshal.GetHRForLastWin32Error() != ERROR_SERVICE_ALREADY_RUNNING) 67 | { 68 | errorMessage = "StartService returned the error: " + 69 | Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()).Message; 70 | NativeMethods.CloseServiceHandle(service); 71 | NativeMethods.CloseServiceHandle(manager); 72 | return false; 73 | } 74 | } 75 | 76 | NativeMethods.CloseServiceHandle(service); 77 | NativeMethods.CloseServiceHandle(manager); 78 | 79 | try 80 | { 81 | // restrict the driver access to system (SY) and builtin admins (BA) 82 | // TODO: replace with a call to IoCreateDeviceSecure in the driver 83 | string filePath = @"\\.\" + id; 84 | FileInfo fileInfo = new FileInfo(filePath); 85 | FileSecurity fileSecurity = fileInfo.GetAccessControl(); 86 | fileSecurity.SetSecurityDescriptorSddlForm("O:BAG:SYD:(A;;FA;;;SY)(A;;FA;;;BA)"); 87 | fileInfo.SetAccessControl(fileSecurity); 88 | } 89 | catch { } 90 | 91 | errorMessage = null; 92 | return true; 93 | } 94 | 95 | public bool Open() 96 | { 97 | device = new SafeFileHandle(NativeMethods.CreateFile(@"\\.\" + id, 98 | FileAccess.GENERIC_READ | FileAccess.GENERIC_WRITE, 0, IntPtr.Zero, 99 | CreationDisposition.OPEN_EXISTING, FileAttributes.FILE_ATTRIBUTE_NORMAL, 100 | IntPtr.Zero), true); 101 | 102 | if (device.IsInvalid) 103 | { 104 | device.Close(); 105 | device.Dispose(); 106 | device = null; 107 | } 108 | 109 | return device != null; 110 | } 111 | 112 | public bool IsOpen 113 | { 114 | get { return device != null; } 115 | } 116 | 117 | public bool DeviceIOControl(IOControlCode ioControlCode, object inBuffer) 118 | { 119 | if (device == null) 120 | return false; 121 | 122 | uint bytesReturned; 123 | bool b = NativeMethods.DeviceIoControl(device, ioControlCode, 124 | inBuffer, inBuffer == null ? 0 : (uint)Marshal.SizeOf(inBuffer), 125 | null, 0, out bytesReturned, IntPtr.Zero); 126 | return b; 127 | } 128 | 129 | public bool DeviceIOControl(IOControlCode ioControlCode, object inBuffer, 130 | ref T outBuffer) 131 | { 132 | if (device == null) 133 | return false; 134 | 135 | object boxedOutBuffer = outBuffer; 136 | uint bytesReturned; 137 | bool b = NativeMethods.DeviceIoControl(device, ioControlCode, 138 | inBuffer, inBuffer == null ? 0 : (uint)Marshal.SizeOf(inBuffer), 139 | boxedOutBuffer, (uint)Marshal.SizeOf(boxedOutBuffer), 140 | out bytesReturned, IntPtr.Zero); 141 | outBuffer = (T)boxedOutBuffer; 142 | return b; 143 | } 144 | 145 | public void Close() 146 | { 147 | if (device != null) 148 | { 149 | device.Close(); 150 | device.Dispose(); 151 | device = null; 152 | } 153 | } 154 | 155 | public bool Delete() 156 | { 157 | IntPtr manager = NativeMethods.OpenSCManager(null, null, 158 | ServiceControlManagerAccessRights.SC_MANAGER_ALL_ACCESS); 159 | 160 | if (manager == IntPtr.Zero) 161 | return false; 162 | 163 | IntPtr service = NativeMethods.OpenService(manager, id, 164 | ServiceAccessRights.SERVICE_ALL_ACCESS); 165 | 166 | if (service == IntPtr.Zero) 167 | return true; 168 | 169 | ServiceStatus status = new ServiceStatus(); 170 | NativeMethods.ControlService(service, ServiceControl.SERVICE_CONTROL_STOP, 171 | ref status); 172 | 173 | NativeMethods.DeleteService(service); 174 | 175 | NativeMethods.CloseServiceHandle(service); 176 | NativeMethods.CloseServiceHandle(manager); 177 | 178 | return true; 179 | } 180 | 181 | private enum ServiceAccessRights : uint 182 | { 183 | SERVICE_ALL_ACCESS = 0xF01FF 184 | } 185 | 186 | private enum ServiceControlManagerAccessRights : uint 187 | { 188 | SC_MANAGER_ALL_ACCESS = 0xF003F 189 | } 190 | 191 | private enum ServiceType : uint 192 | { 193 | SERVICE_KERNEL_DRIVER = 1, 194 | SERVICE_FILE_SYSTEM_DRIVER = 2 195 | } 196 | 197 | private enum StartType : uint 198 | { 199 | SERVICE_BOOT_START = 0, 200 | SERVICE_SYSTEM_START = 1, 201 | SERVICE_AUTO_START = 2, 202 | SERVICE_DEMAND_START = 3, 203 | SERVICE_DISABLED = 4 204 | } 205 | 206 | private enum ErrorControl : uint 207 | { 208 | SERVICE_ERROR_IGNORE = 0, 209 | SERVICE_ERROR_NORMAL = 1, 210 | SERVICE_ERROR_SEVERE = 2, 211 | SERVICE_ERROR_CRITICAL = 3 212 | } 213 | 214 | private enum ServiceControl : uint 215 | { 216 | SERVICE_CONTROL_STOP = 1, 217 | SERVICE_CONTROL_PAUSE = 2, 218 | SERVICE_CONTROL_CONTINUE = 3, 219 | SERVICE_CONTROL_INTERROGATE = 4, 220 | SERVICE_CONTROL_SHUTDOWN = 5, 221 | SERVICE_CONTROL_PARAMCHANGE = 6, 222 | SERVICE_CONTROL_NETBINDADD = 7, 223 | SERVICE_CONTROL_NETBINDREMOVE = 8, 224 | SERVICE_CONTROL_NETBINDENABLE = 9, 225 | SERVICE_CONTROL_NETBINDDISABLE = 10, 226 | SERVICE_CONTROL_DEVICEEVENT = 11, 227 | SERVICE_CONTROL_HARDWAREPROFILECHANGE = 12, 228 | SERVICE_CONTROL_POWEREVENT = 13, 229 | SERVICE_CONTROL_SESSIONCHANGE = 14 230 | } 231 | 232 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 233 | private struct ServiceStatus 234 | { 235 | public uint dwServiceType; 236 | public uint dwCurrentState; 237 | public uint dwControlsAccepted; 238 | public uint dwWin32ExitCode; 239 | public uint dwServiceSpecificExitCode; 240 | public uint dwCheckPoint; 241 | public uint dwWaitHint; 242 | } 243 | 244 | private enum FileAccess : uint 245 | { 246 | GENERIC_READ = 0x80000000, 247 | GENERIC_WRITE = 0x40000000 248 | } 249 | 250 | private enum CreationDisposition : uint 251 | { 252 | CREATE_NEW = 1, 253 | CREATE_ALWAYS = 2, 254 | OPEN_EXISTING = 3, 255 | OPEN_ALWAYS = 4, 256 | TRUNCATE_EXISTING = 5 257 | } 258 | 259 | private enum FileAttributes : uint 260 | { 261 | FILE_ATTRIBUTE_NORMAL = 0x80 262 | } 263 | 264 | private const int 265 | ERROR_SERVICE_EXISTS = unchecked((int)0x80070431), 266 | ERROR_SERVICE_ALREADY_RUNNING = unchecked((int)0x80070420); 267 | 268 | private static class NativeMethods 269 | { 270 | private const string ADVAPI = "advapi32.dll"; 271 | private const string KERNEL = "kernel32.dll"; 272 | 273 | [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi)] 274 | public static extern IntPtr OpenSCManager(string machineName, 275 | string databaseName, ServiceControlManagerAccessRights dwAccess); 276 | 277 | [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi)] 278 | [return: MarshalAs(UnmanagedType.Bool)] 279 | public static extern bool CloseServiceHandle(IntPtr hSCObject); 280 | 281 | [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi, 282 | SetLastError = true)] 283 | public static extern IntPtr CreateService(IntPtr hSCManager, 284 | string lpServiceName, string lpDisplayName, 285 | ServiceAccessRights dwDesiredAccess, ServiceType dwServiceType, 286 | StartType dwStartType, ErrorControl dwErrorControl, 287 | string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId, 288 | string lpDependencies, string lpServiceStartName, string lpPassword); 289 | 290 | [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi, 291 | SetLastError = true)] 292 | public static extern IntPtr OpenService(IntPtr hSCManager, 293 | string lpServiceName, ServiceAccessRights dwDesiredAccess); 294 | 295 | [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi, 296 | SetLastError = true)] 297 | [return: MarshalAs(UnmanagedType.Bool)] 298 | public static extern bool DeleteService(IntPtr hService); 299 | 300 | [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi, 301 | SetLastError = true)] 302 | [return: MarshalAs(UnmanagedType.Bool)] 303 | public static extern bool StartService(IntPtr hService, 304 | uint dwNumServiceArgs, string[] lpServiceArgVectors); 305 | 306 | [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi, 307 | SetLastError = true)] 308 | [return: MarshalAs(UnmanagedType.Bool)] 309 | public static extern bool ControlService(IntPtr hService, 310 | ServiceControl dwControl, ref ServiceStatus lpServiceStatus); 311 | 312 | [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] 313 | public static extern bool DeviceIoControl(SafeFileHandle device, 314 | IOControlCode ioControlCode, 315 | [MarshalAs(UnmanagedType.AsAny)][In] object inBuffer, 316 | uint inBufferSize, 317 | [MarshalAs(UnmanagedType.AsAny)][Out] object outBuffer, 318 | uint nOutBufferSize, out uint bytesReturned, IntPtr overlapped); 319 | 320 | [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi, 321 | SetLastError = true)] 322 | public static extern IntPtr CreateFile(string lpFileName, 323 | FileAccess dwDesiredAccess, uint dwShareMode, 324 | IntPtr lpSecurityAttributes, CreationDisposition dwCreationDisposition, 325 | FileAttributes dwFlagsAndAttributes, IntPtr hTemplateFile); 326 | } 327 | } 328 | } 329 | -------------------------------------------------------------------------------- /OHWM/Opcode.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This Source Code Form is subject to the terms of the Mozilla Public 4 | License, v. 2.0. If a copy of the MPL was not distributed with this 5 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | 7 | Copyright (C) 2010 Michael Möller 8 | 9 | */ 10 | 11 | using System; 12 | using System.Reflection; 13 | using System.Runtime.InteropServices; 14 | 15 | namespace OpenHardwareMonitor.Hardware 16 | { 17 | internal static class Opcode 18 | { 19 | 20 | private static IntPtr codeBuffer; 21 | private static ulong size; 22 | 23 | public static void Open() 24 | { 25 | byte[] rdtscCode; 26 | byte[] cpuidCode; 27 | if (IntPtr.Size == 4) 28 | { 29 | rdtscCode = RDTSC_32; 30 | cpuidCode = CPUID_32; 31 | } 32 | else 33 | { 34 | rdtscCode = RDTSC_64; 35 | 36 | if (OperatingSystem.IsUnix) 37 | { // Unix 38 | cpuidCode = CPUID_64_LINUX; 39 | } 40 | else 41 | { // Windows 42 | cpuidCode = CPUID_64_WINDOWS; 43 | } 44 | } 45 | 46 | size = (ulong)(rdtscCode.Length + cpuidCode.Length); 47 | 48 | if (OperatingSystem.IsUnix) 49 | { // Unix 50 | Assembly assembly = 51 | Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " + 52 | "PublicKeyToken=0738eb9f132ed756"); 53 | 54 | Type syscall = assembly.GetType("Mono.Unix.Native.Syscall"); 55 | MethodInfo mmap = syscall.GetMethod("mmap"); 56 | 57 | Type mmapProts = assembly.GetType("Mono.Unix.Native.MmapProts"); 58 | object mmapProtsParam = Enum.ToObject(mmapProts, 59 | (int)mmapProts.GetField("PROT_READ").GetValue(null) | 60 | (int)mmapProts.GetField("PROT_WRITE").GetValue(null) | 61 | (int)mmapProts.GetField("PROT_EXEC").GetValue(null)); 62 | 63 | Type mmapFlags = assembly.GetType("Mono.Unix.Native.MmapFlags"); 64 | object mmapFlagsParam = Enum.ToObject(mmapFlags, 65 | (int)mmapFlags.GetField("MAP_ANONYMOUS").GetValue(null) | 66 | (int)mmapFlags.GetField("MAP_PRIVATE").GetValue(null)); 67 | 68 | codeBuffer = (IntPtr)mmap.Invoke(null, new object[] { IntPtr.Zero, 69 | size, mmapProtsParam, mmapFlagsParam, -1, 0 }); 70 | } 71 | else 72 | { // Windows 73 | codeBuffer = NativeMethods.VirtualAlloc(IntPtr.Zero, 74 | (UIntPtr)size, AllocationType.COMMIT | AllocationType.RESERVE, 75 | MemoryProtection.EXECUTE_READWRITE); 76 | } 77 | 78 | Marshal.Copy(rdtscCode, 0, codeBuffer, rdtscCode.Length); 79 | 80 | Rdtsc = Marshal.GetDelegateForFunctionPointer( 81 | codeBuffer, typeof(RdtscDelegate)) as RdtscDelegate; 82 | 83 | IntPtr cpuidAddress = (IntPtr)((long)codeBuffer + rdtscCode.Length); 84 | Marshal.Copy(cpuidCode, 0, cpuidAddress, cpuidCode.Length); 85 | 86 | Cpuid = Marshal.GetDelegateForFunctionPointer( 87 | cpuidAddress, typeof(CpuidDelegate)) as CpuidDelegate; 88 | } 89 | 90 | public static void Close() 91 | { 92 | Rdtsc = null; 93 | Cpuid = null; 94 | 95 | if (OperatingSystem.IsUnix) 96 | { // Unix 97 | Assembly assembly = 98 | Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " + 99 | "PublicKeyToken=0738eb9f132ed756"); 100 | 101 | Type syscall = assembly.GetType("Mono.Unix.Native.Syscall"); 102 | MethodInfo munmap = syscall.GetMethod("munmap"); 103 | munmap.Invoke(null, new object[] { codeBuffer, size }); 104 | 105 | } 106 | else 107 | { // Windows 108 | NativeMethods.VirtualFree(codeBuffer, UIntPtr.Zero, 109 | FreeType.RELEASE); 110 | } 111 | } 112 | 113 | [UnmanagedFunctionPointer(CallingConvention.StdCall)] 114 | public delegate ulong RdtscDelegate(); 115 | 116 | public static RdtscDelegate Rdtsc; 117 | 118 | // unsigned __int64 __stdcall rdtsc() { 119 | // return __rdtsc(); 120 | // } 121 | 122 | private static readonly byte[] RDTSC_32 = new byte[] { 123 | 0x0F, 0x31, // rdtsc 124 | 0xC3 // ret 125 | }; 126 | 127 | private static readonly byte[] RDTSC_64 = new byte[] { 128 | 0x0F, 0x31, // rdtsc 129 | 0x48, 0xC1, 0xE2, 0x20, // shl rdx, 20h 130 | 0x48, 0x0B, 0xC2, // or rax, rdx 131 | 0xC3 // ret 132 | }; 133 | 134 | [UnmanagedFunctionPointer(CallingConvention.StdCall)] 135 | public delegate bool CpuidDelegate(uint index, uint ecxValue, 136 | out uint eax, out uint ebx, out uint ecx, out uint edx); 137 | 138 | public static CpuidDelegate Cpuid; 139 | 140 | 141 | // void __stdcall cpuidex(unsigned int index, unsigned int ecxValue, 142 | // unsigned int* eax, unsigned int* ebx, unsigned int* ecx, 143 | // unsigned int* edx) 144 | // { 145 | // int info[4]; 146 | // __cpuidex(info, index, ecxValue); 147 | // *eax = info[0]; 148 | // *ebx = info[1]; 149 | // *ecx = info[2]; 150 | // *edx = info[3]; 151 | // } 152 | 153 | private static readonly byte[] CPUID_32 = new byte[] { 154 | 0x55, // push ebp 155 | 0x8B, 0xEC, // mov ebp, esp 156 | 0x83, 0xEC, 0x10, // sub esp, 10h 157 | 0x8B, 0x45, 0x08, // mov eax, dword ptr [ebp+8] 158 | 0x8B, 0x4D, 0x0C, // mov ecx, dword ptr [ebp+0Ch] 159 | 0x53, // push ebx 160 | 0x0F, 0xA2, // cpuid 161 | 0x56, // push esi 162 | 0x8D, 0x75, 0xF0, // lea esi, [info] 163 | 0x89, 0x06, // mov dword ptr [esi],eax 164 | 0x8B, 0x45, 0x10, // mov eax, dword ptr [eax] 165 | 0x89, 0x5E, 0x04, // mov dword ptr [esi+4], ebx 166 | 0x89, 0x4E, 0x08, // mov dword ptr [esi+8], ecx 167 | 0x89, 0x56, 0x0C, // mov dword ptr [esi+0Ch], edx 168 | 0x8B, 0x4D, 0xF0, // mov ecx, dword ptr [info] 169 | 0x89, 0x08, // mov dword ptr [eax], ecx 170 | 0x8B, 0x45, 0x14, // mov eax, dword ptr [ebx] 171 | 0x8B, 0x4D, 0xF4, // mov ecx, dword ptr [ebp-0Ch] 172 | 0x89, 0x08, // mov dword ptr [eax], ecx 173 | 0x8B, 0x45, 0x18, // mov eax, dword ptr [ecx] 174 | 0x8B, 0x4D, 0xF8, // mov ecx, dword ptr [ebp-8] 175 | 0x89, 0x08, // mov dword ptr [eax], ecx 176 | 0x8B, 0x45, 0x1C, // mov eax, dword ptr [edx] 177 | 0x8B, 0x4D, 0xFC, // mov ecx, dword ptr [ebp-4] 178 | 0x5E, // pop esi 179 | 0x89, 0x08, // mov dword ptr [eax], ecx 180 | 0x5B, // pop ebx 181 | 0xC9, // leave 182 | 0xC2, 0x18, 0x00 // ret 18h 183 | }; 184 | 185 | private static readonly byte[] CPUID_64_WINDOWS = new byte[] { 186 | 0x48, 0x89, 0x5C, 0x24, 0x08, // mov qword ptr [rsp+8], rbx 187 | 0x8B, 0xC1, // mov eax, ecx 188 | 0x8B, 0xCA, // mov ecx, edx 189 | 0x0F, 0xA2, // cpuid 190 | 0x41, 0x89, 0x00, // mov dword ptr [r8], eax 191 | 0x48, 0x8B, 0x44, 0x24, 0x28, // mov rax, qword ptr [rsp+28h] 192 | 0x41, 0x89, 0x19, // mov dword ptr [r9], ebx 193 | 0x48, 0x8B, 0x5C, 0x24, 0x08, // mov rbx, qword ptr [rsp+8] 194 | 0x89, 0x08, // mov dword ptr [rax], ecx 195 | 0x48, 0x8B, 0x44, 0x24, 0x30, // mov rax, qword ptr [rsp+30h] 196 | 0x89, 0x10, // mov dword ptr [rax], edx 197 | 0xC3 // ret 198 | }; 199 | 200 | private static readonly byte[] CPUID_64_LINUX = new byte[] { 201 | 0x49, 0x89, 0xD2, // mov r10, rdx 202 | 0x49, 0x89, 0xCB, // mov r11, rcx 203 | 0x53, // push rbx 204 | 0x89, 0xF8, // mov eax, edi 205 | 0x89, 0xF1, // mov ecx, esi 206 | 0x0F, 0xA2, // cpuid 207 | 0x41, 0x89, 0x02, // mov dword ptr [r10], eax 208 | 0x41, 0x89, 0x1B, // mov dword ptr [r11], ebx 209 | 0x41, 0x89, 0x08, // mov dword ptr [r8], ecx 210 | 0x41, 0x89, 0x11, // mov dword ptr [r9], edx 211 | 0x5B, // pop rbx 212 | 0xC3, // ret 213 | }; 214 | 215 | public static bool CpuidTx(uint index, uint ecxValue, 216 | out uint eax, out uint ebx, out uint ecx, out uint edx, 217 | GroupAffinity affinity) 218 | { 219 | var previousAffinity = ThreadAffinity.Set(affinity); 220 | 221 | if (previousAffinity == GroupAffinity.Undefined) 222 | { 223 | eax = ebx = ecx = edx = 0; 224 | return false; 225 | } 226 | 227 | Cpuid(index, ecxValue, out eax, out ebx, out ecx, out edx); 228 | 229 | ThreadAffinity.Set(previousAffinity); 230 | return true; 231 | } 232 | 233 | [Flags()] 234 | public enum AllocationType : uint 235 | { 236 | COMMIT = 0x1000, 237 | RESERVE = 0x2000, 238 | RESET = 0x80000, 239 | LARGE_PAGES = 0x20000000, 240 | PHYSICAL = 0x400000, 241 | TOP_DOWN = 0x100000, 242 | WRITE_WATCH = 0x200000 243 | } 244 | 245 | [Flags()] 246 | public enum MemoryProtection : uint 247 | { 248 | EXECUTE = 0x10, 249 | EXECUTE_READ = 0x20, 250 | EXECUTE_READWRITE = 0x40, 251 | EXECUTE_WRITECOPY = 0x80, 252 | NOACCESS = 0x01, 253 | READONLY = 0x02, 254 | READWRITE = 0x04, 255 | WRITECOPY = 0x08, 256 | GUARD = 0x100, 257 | NOCACHE = 0x200, 258 | WRITECOMBINE = 0x400 259 | } 260 | 261 | [Flags] 262 | public enum FreeType 263 | { 264 | DECOMMIT = 0x4000, 265 | RELEASE = 0x8000 266 | } 267 | 268 | private static class NativeMethods 269 | { 270 | private const string KERNEL = "kernel32.dll"; 271 | 272 | [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] 273 | public static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, 274 | AllocationType flAllocationType, MemoryProtection flProtect); 275 | 276 | [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] 277 | public static extern bool VirtualFree(IntPtr lpAddress, UIntPtr dwSize, 278 | FreeType dwFreeType); 279 | } 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /OHWM/OperatingSystem.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This Source Code Form is subject to the terms of the Mozilla Public 4 | License, v. 2.0. If a copy of the MPL was not distributed with this 5 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | 7 | Copyright (C) 2012-2020 Michael Möller 8 | 9 | */ 10 | 11 | using System; 12 | using System.Diagnostics; 13 | using System.Runtime.InteropServices; 14 | 15 | namespace OpenHardwareMonitor.Hardware 16 | { 17 | public static class OperatingSystem 18 | { 19 | 20 | static OperatingSystem() 21 | { 22 | int p = (int)Environment.OSVersion.Platform; 23 | IsUnix = (p == 4) || (p == 6) || (p == 128); 24 | 25 | Is64BitOperatingSystem = GetIs64BitOperatingSystem(); 26 | } 27 | 28 | public static bool IsUnix { get; } 29 | 30 | public static bool Is64BitOperatingSystem { get; } 31 | 32 | private static bool GetIs64BitOperatingSystem() 33 | { 34 | if (IntPtr.Size == 8) 35 | return true; 36 | 37 | try 38 | { 39 | bool wow64Process; 40 | bool result = IsWow64Process( 41 | Process.GetCurrentProcess().Handle, out wow64Process); 42 | 43 | return result && wow64Process; 44 | } 45 | catch (EntryPointNotFoundException) 46 | { 47 | return false; 48 | } 49 | } 50 | 51 | [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 52 | [return: MarshalAs(UnmanagedType.Bool)] 53 | private static extern bool IsWow64Process(IntPtr hProcess, 54 | out bool wow64Process); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /OHWM/ThreadAffinity.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This Source Code Form is subject to the terms of the Mozilla Public 4 | License, v. 2.0. If a copy of the MPL was not distributed with this 5 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | 7 | Copyright (C) 2010-2020 Michael Möller 8 | 9 | */ 10 | 11 | using System; 12 | using System.Runtime.InteropServices; 13 | 14 | namespace OpenHardwareMonitor.Hardware 15 | { 16 | 17 | internal static class ThreadAffinity 18 | { 19 | 20 | static ThreadAffinity() 21 | { 22 | ProcessorGroupCount = GetProcessorGroupCount(); 23 | } 24 | 25 | private static int GetProcessorGroupCount() 26 | { 27 | if (OperatingSystem.IsUnix) 28 | return 1; 29 | 30 | try 31 | { 32 | return NativeMethods.GetActiveProcessorGroupCount(); 33 | } 34 | catch 35 | { 36 | return 1; 37 | } 38 | } 39 | 40 | public static int ProcessorGroupCount { get; } 41 | 42 | public static bool IsValid(GroupAffinity affinity) 43 | { 44 | if (OperatingSystem.IsUnix) 45 | { 46 | if (affinity.Group > 0) 47 | return false; 48 | } 49 | 50 | try 51 | { 52 | var previous = Set(affinity); 53 | if (previous == GroupAffinity.Undefined) 54 | return false; 55 | Set(previous); 56 | return true; 57 | } 58 | catch 59 | { 60 | return false; 61 | } 62 | } 63 | 64 | /// 65 | /// Sets the processor group affinity for the current thread. 66 | /// 67 | /// The processor group affinity. 68 | /// The previous processor group affinity. 69 | public static GroupAffinity Set(GroupAffinity affinity) 70 | { 71 | if (affinity == GroupAffinity.Undefined) 72 | return GroupAffinity.Undefined; 73 | 74 | if (OperatingSystem.IsUnix) 75 | { 76 | if (affinity.Group > 0) 77 | throw new ArgumentOutOfRangeException("affinity.Group"); 78 | 79 | ulong result = 0; 80 | if (NativeMethods.sched_getaffinity(0, (IntPtr)8, ref result) != 0) 81 | return GroupAffinity.Undefined; 82 | 83 | ulong mask = affinity.Mask; 84 | if (NativeMethods.sched_setaffinity(0, (IntPtr)8, ref mask) != 0) 85 | return GroupAffinity.Undefined; 86 | 87 | return new GroupAffinity(0, result); 88 | } 89 | else 90 | { 91 | UIntPtr uIntPtrMask; 92 | try 93 | { 94 | uIntPtrMask = (UIntPtr)affinity.Mask; 95 | } 96 | catch (OverflowException) 97 | { 98 | throw new ArgumentOutOfRangeException("affinity.Mask"); 99 | } 100 | 101 | var groupAffinity = new NativeMethods.GROUP_AFFINITY 102 | { 103 | Group = affinity.Group, 104 | Mask = uIntPtrMask 105 | }; 106 | 107 | var currentThread = NativeMethods.GetCurrentThread(); 108 | 109 | try 110 | { 111 | if (NativeMethods.SetThreadGroupAffinity(currentThread, 112 | ref groupAffinity, out var previousGroupAffinity)) 113 | { 114 | return new GroupAffinity(previousGroupAffinity.Group, 115 | (ulong)previousGroupAffinity.Mask); 116 | } 117 | else 118 | { 119 | return GroupAffinity.Undefined; 120 | } 121 | } 122 | catch (EntryPointNotFoundException) 123 | { 124 | if (affinity.Group > 0) 125 | throw new ArgumentOutOfRangeException("affinity.Group"); 126 | 127 | var previous = (ulong)NativeMethods.SetThreadAffinityMask( 128 | currentThread, uIntPtrMask); 129 | 130 | return new GroupAffinity(0, previous); 131 | } 132 | } 133 | } 134 | 135 | private static class NativeMethods 136 | { 137 | private const string KERNEL = "kernel32.dll"; 138 | 139 | [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] 140 | public static extern UIntPtr 141 | SetThreadAffinityMask(IntPtr handle, UIntPtr mask); 142 | 143 | [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] 144 | public static extern IntPtr GetCurrentThread(); 145 | 146 | [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] 147 | public static extern ushort GetActiveProcessorGroupCount(); 148 | 149 | [StructLayout(LayoutKind.Sequential, Pack = 4)] 150 | public struct GROUP_AFFINITY 151 | { 152 | public UIntPtr Mask; 153 | [MarshalAs(UnmanagedType.U2)] 154 | public ushort Group; 155 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, 156 | ArraySubType = UnmanagedType.U2)] 157 | public ushort[] Reserved; 158 | } 159 | 160 | [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] 161 | public static extern bool SetThreadGroupAffinity( 162 | IntPtr thread, 163 | ref GROUP_AFFINITY groupAffinity, 164 | out GROUP_AFFINITY previousGroupAffinity); 165 | 166 | private const string LIBC = "libc"; 167 | 168 | [DllImport(LIBC)] 169 | public static extern int sched_getaffinity(int pid, IntPtr maskSize, 170 | ref ulong mask); 171 | 172 | [DllImport(LIBC)] 173 | public static extern int sched_setaffinity(int pid, IntPtr maskSize, 174 | ref ulong mask); 175 | } 176 | } 177 | } 178 | 179 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | // Setting ComVisible to false makes the types in this assembly not visible 4 | // to COM components. If you need to access a type in this assembly from 5 | // COM, set the ComVisible attribute to true on that type. 6 | [assembly: ComVisible(true)] 7 | 8 | // The following GUID is for the ID of the typelib if this project is exposed to COM 9 | [assembly: Guid("39c55831-97a2-498d-a9dd-27bf677e579a")] 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZenStates-Core 2 | This project aims to provide a common functions for full SMU control on AMD Zen platform. 3 | The library is used in ZenTimings and ZenStates projects. 4 | 5 | ## CPU Support 6 | The following AMD Zen-based codenames are supported 7 | * SummitRidge 8 | * Whitehaven 9 | * Naples 10 | * RavenRidge 11 | * PinnacleRidge 12 | * Colfax 13 | * Picasso 14 | * FireFlight 15 | * Matisse 16 | * CastlePeak 17 | * Rome 18 | * Dali 19 | * Renoir 20 | * VanGogh 21 | * Vermeer 22 | * Chagall 23 | * Milan 24 | * Cezanne 25 | * Rembrandt 26 | * Lucienne 27 | * Raphael 28 | * Phoenix 29 | * Phoenix2 30 | * Mendocino 31 | * Genoa 32 | * StormPeak 33 | * DragonRange 34 | * Mero 35 | * HawkPoint 36 | * StrixPoint 37 | * GraniteRidge 38 | * KrackanPoint 39 | * StrixHalo 40 | * Turin 41 | * Bergamo 42 | 43 | ## How To 44 | First, reference the DLL in your .NET project and import it. 45 | ```c# 46 | using ZenStates.Core; 47 | ``` 48 | Then initialize it. Cpu is the main module. 49 | ```c# 50 | private readonly Cpu cpu = new Cpu(); 51 | ``` 52 | 53 | ## Modules 54 | ### `Cpu.info` 55 | 56 | | field | type | 57 | |----------------|-------------| 58 | | cpuid | uint | 59 | | family | Family | 60 | | codeName | CodeName | 61 | | cpuName | string | 62 | | packageType | PackageType | 63 | | baseModel | uint | 64 | | extModel | uint | 65 | | model | uint | 66 | | ccds | uint | 67 | | ccxs | uint | 68 | | coresPerCcx | uint | 69 | | cores | uint | 70 | | logicalCores | uint | 71 | | physicalCores | uint | 72 | | threadsPerCore | uint | 73 | | patchLevel | uint | 74 | | coreDisableMap | uint | 75 | | svi2 | SVI2 | 76 | 77 | 78 | where svi2 exposes the following fields corresponding to the SVI2 power planes 79 | 80 | | field | type | 81 | |----------------|-------------| 82 | | coreAddress | uint | 83 | | socAddress | uint | 84 | 85 | ### `Cpu.systemInfo` 86 | 87 | The module combines `Cpu.info` with additional information about the motherboard 88 | 89 | ## Projects used 90 | [ryzen_smu (gitlab)](https://gitlab.com/leogx9r/ryzen_smu/) 91 | [ryzen_nb_smu (github)](https://github.com/flygoat/ryzen_nb_smu) 92 | [zenpower (github)](https://github.com/ocerman/zenpower) 93 | [Linux kernel (github)](https://github.com/torvalds/linux) 94 | [AMD's public documentation](https://www.amd.com/en/support/tech-docs) 95 | [Open Hardware Monitor](https://github.com/openhardwaremonitor/openhardwaremonitor) 96 | 97 | with the help of patrickschur, leogx9r, PJVol, FlyGoat, sbski, 1usmus 98 | -------------------------------------------------------------------------------- /SMUCommands/BaseSMUCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ZenStates.Core.SMUCommands 4 | { 5 | internal abstract class BaseSMUCommand : IDisposable 6 | { 7 | internal SMU smu; 8 | internal CmdResult result; 9 | private bool disposedValue; 10 | 11 | protected BaseSMUCommand(SMU smuInstance, uint maxArgs = Constants.DEFAULT_MAILBOX_ARGS) 12 | { 13 | if (smuInstance != null) 14 | { 15 | smu = smuInstance; 16 | } 17 | result = new CmdResult(maxArgs); 18 | } 19 | 20 | public virtual bool CanExecute() => smu != null; 21 | public virtual CmdResult Execute() 22 | { 23 | // reset args to 0, to avoid getting the incoming parameter as a result in case of an error 24 | if (!result.Success) 25 | result.args = Utils.MakeCmdArgs(); 26 | 27 | Dispose(); 28 | return result; 29 | } 30 | protected virtual void Dispose(bool disposing) 31 | { 32 | if (!disposedValue) 33 | { 34 | if (disposing) 35 | { 36 | smu = null; 37 | } 38 | 39 | disposedValue = true; 40 | } 41 | } 42 | public void Dispose() 43 | { 44 | // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method 45 | Dispose(disposing: true); 46 | GC.SuppressFinalize(this); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /SMUCommands/CmdResult.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class CmdResult 4 | { 5 | public SMU.Status status; 6 | public uint[] args; 7 | public bool Success => status == SMU.Status.OK; 8 | 9 | public CmdResult(uint maxArgs) 10 | { 11 | args = Utils.MakeCmdArgs(maxArgs: maxArgs); 12 | status = SMU.Status.FAILED; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SMUCommands/GetBoostLimitFrequency.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class GetBoostLimitFrequency : BaseSMUCommand 4 | { 5 | public GetBoostLimitFrequency(SMU smu) : base(smu) { } 6 | public override CmdResult Execute() 7 | { 8 | if (CanExecute()) 9 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetBoostLimitFrequency, ref result.args); 10 | 11 | return base.Execute(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SMUCommands/GetCorePerformanceData.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class GetCorePerformanceData : BaseSMUCommand 4 | { 5 | public GetCorePerformanceData(SMU smu) : base(smu) { } 6 | public CmdResult Execute(uint coreIndex) 7 | { 8 | if (CanExecute()) 9 | { 10 | result.args[0] = coreIndex; 11 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetPerformanceData, ref result.args); 12 | } 13 | 14 | return base.Execute(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SMUCommands/GetDramAddress.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class GetDramAddress : BaseSMUCommand 4 | { 5 | public GetDramAddress(SMU smu) : base(smu) { } 6 | 7 | public override CmdResult Execute() 8 | { 9 | if (CanExecute()) 10 | { 11 | switch (smu.SMU_TYPE) 12 | { 13 | // SummitRidge, PinnacleRidge, Colfax 14 | case SMU.SmuType.TYPE_CPU0: 15 | case SMU.SmuType.TYPE_CPU1: 16 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetDramBaseAddress - 1, ref result.args); 17 | if (!result.Success) 18 | break; 19 | 20 | // reset args 21 | result.args = Utils.MakeCmdArgs(); 22 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetDramBaseAddress, ref result.args); 23 | if (!result.Success) 24 | break; 25 | 26 | // save base address 27 | uint address = result.args[0]; 28 | 29 | // reset args 30 | result.args = Utils.MakeCmdArgs(); 31 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetDramBaseAddress + 2, ref result.args); 32 | 33 | // restore base address 34 | if (result.Success) 35 | result.args = Utils.MakeCmdArgs(address); 36 | 37 | break; 38 | 39 | // Matisse, CastlePeak, Rome, Vermeer, Raphael, Chagall?, Milan? 40 | case SMU.SmuType.TYPE_CPU2: 41 | case SMU.SmuType.TYPE_CPU3: 42 | case SMU.SmuType.TYPE_CPU4: 43 | // Renoir, Cezanne, VanGogh, Rembrandt 44 | case SMU.SmuType.TYPE_APU1: 45 | case SMU.SmuType.TYPE_APU2: 46 | result.args = Utils.MakeCmdArgs(new uint[2] { 1, 1 }); 47 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetDramBaseAddress, ref result.args); 48 | break; 49 | 50 | // RavenRidge, RavenRidge2, Picasso 51 | case SMU.SmuType.TYPE_APU0: 52 | uint[] parts = new uint[2]; 53 | 54 | result.args = Utils.MakeCmdArgs(3); 55 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetDramBaseAddress - 1, ref result.args); 56 | if (!result.Success) 57 | break; 58 | 59 | result.args = Utils.MakeCmdArgs(3); 60 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetDramBaseAddress, ref result.args); 61 | if (!result.Success) 62 | break; 63 | 64 | // First base 65 | parts[0] = result.args[0]; 66 | 67 | result.args = Utils.MakeCmdArgs(5); 68 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetDramBaseAddress - 1, ref result.args); 69 | if (!result.Success) 70 | break; 71 | 72 | result.args = Utils.MakeCmdArgs(5); 73 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetDramBaseAddress, ref result.args); 74 | if (!result.Success) 75 | break; 76 | 77 | // Second base 78 | parts[1] = result.args[0]; 79 | 80 | // return both base addresses 81 | result.args = Utils.MakeCmdArgs(new uint[2] { parts[0], parts[1] }); 82 | break; 83 | } 84 | } 85 | 86 | return base.Execute(); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /SMUCommands/GetIsOverclockable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ZenStates.Core.SMUCommands 4 | { 5 | internal class GetIsOverclockable : BaseSMUCommand 6 | { 7 | public bool IsOverclockable { get; protected set; } 8 | public GetIsOverclockable(SMU smu) : base(smu) { } 9 | public override CmdResult Execute() 10 | { 11 | if (CanExecute()) 12 | { 13 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_IsOverclockable, ref result.args); 14 | 15 | if (result.Success) 16 | { 17 | IsOverclockable = Convert.ToBoolean(result.args[0] & 1); 18 | } 19 | } 20 | 21 | return base.Execute(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SMUCommands/GetLN2Mode.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class GetLN2Mode : BaseSMUCommand 4 | { 5 | public GetLN2Mode(SMU smu) : base(smu) { } 6 | public override CmdResult Execute() 7 | { 8 | if (CanExecute()) 9 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetLN2Mode, ref result.args); 10 | 11 | return base.Execute(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SMUCommands/GetPBOScalar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ZenStates.Core.SMUCommands 4 | { 5 | internal class GetPBOScalar : BaseSMUCommand 6 | { 7 | public float Scalar { get; protected set; } 8 | public GetPBOScalar(SMU smu) : base(smu) 9 | { 10 | Scalar = 0.0f; 11 | } 12 | 13 | public override CmdResult Execute() 14 | { 15 | if (CanExecute()) 16 | { 17 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetPBOScalar, ref result.args); 18 | if (result.Success) 19 | { 20 | byte[] bytes = BitConverter.GetBytes(result.args[0]); 21 | Scalar = BitConverter.ToSingle(bytes, 0); 22 | if (Scalar < Constants.PBO_SCALAR_MIN || Scalar > Constants.PBO_SCALAR_MAX) 23 | Scalar = Constants.PBO_SCALAR_DEFAULT; 24 | } 25 | } 26 | 27 | return base.Execute(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SMUCommands/GetPsmMarginSingleCore.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class GetPsmMarginSingleCore : BaseSMUCommand 4 | { 5 | public GetPsmMarginSingleCore(SMU smu) : base(smu) { } 6 | public CmdResult Execute(uint coreMask) 7 | { 8 | if (CanExecute()) 9 | { 10 | result.args[0] = coreMask & 0xfff00000; 11 | 12 | if (smu.Rsmu.SMU_MSG_GetDldoPsmMargin > 0) 13 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetDldoPsmMargin, ref result.args); 14 | else 15 | result.status = smu.SendMp1Command(smu.Mp1Smu.SMU_MSG_GetDldoPsmMargin, ref result.args); 16 | } 17 | 18 | return base.Execute(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SMUCommands/GetSmuVersion.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class GetSmuVersion : BaseSMUCommand 4 | { 5 | public GetSmuVersion(SMU smu) : base(smu) { } 6 | public override CmdResult Execute() 7 | { 8 | if (CanExecute()) 9 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetSmuVersion, ref result.args); 10 | 11 | return base.Execute(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SMUCommands/GetTableVersion.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class GetTableVersion : BaseSMUCommand 4 | { 5 | public GetTableVersion(SMU smu) : base(smu) { } 6 | public override CmdResult Execute() 7 | { 8 | if (CanExecute()) 9 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_GetTableVersion, ref result.args); 10 | 11 | return base.Execute(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SMUCommands/SendTestMessage.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class SendTestMessage : BaseSMUCommand 4 | { 5 | private readonly Mailbox mbox; 6 | 7 | public bool IsSumCorrect = false; 8 | public SendTestMessage(SMU smu, Mailbox mbox = null) : base(smu) 9 | { 10 | this.mbox = mbox ?? smu.Rsmu; 11 | } 12 | public CmdResult Execute(uint testArg = 1) 13 | { 14 | if (CanExecute()) 15 | { 16 | result.args[0] = testArg; 17 | result.status = smu.SendSmuCommand(mbox, mbox.SMU_MSG_TestMessage, ref result.args); 18 | this.IsSumCorrect = result.args[0] == testArg + 1; 19 | } 20 | 21 | return base.Execute(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SMUCommands/SetBoostLimitAllCore.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class SetBoostLimitAllCore : BaseSMUCommand 4 | { 5 | public SetBoostLimitAllCore(SMU smu) : base(smu) { } 6 | public CmdResult Execute(uint frequency) 7 | { 8 | if (CanExecute()) 9 | { 10 | result.args[0] = frequency & 0xfffff; 11 | uint cmd = smu.Rsmu.SMU_MSG_SetBoostLimitFrequencyAllCores; 12 | if (cmd != 0) 13 | result.status = smu.SendRsmuCommand(cmd, ref result.args); 14 | else 15 | result.status = smu.SendMp1Command(smu.Mp1Smu.SMU_MSG_SetBoostLimitFrequencyAllCores, ref result.args); 16 | } 17 | 18 | return base.Execute(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SMUCommands/SetFrequencyAllCore.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class SetFrequencyAllCore : BaseSMUCommand 4 | { 5 | public SetFrequencyAllCore(SMU smu) : base(smu) { } 6 | public CmdResult Execute(uint frequency) 7 | { 8 | if (CanExecute()) 9 | { 10 | result.args[0] = frequency & 0xfffff; 11 | // TODO: Add Manual OC mode 12 | // TODO: Add lo and hi frequency limits 13 | uint cmd = smu.Rsmu.SMU_MSG_SetOverclockFrequencyAllCores; 14 | if (cmd != 0) 15 | result.status = smu.SendRsmuCommand(cmd, ref result.args); 16 | else 17 | result.status = smu.SendMp1Command(smu.Mp1Smu.SMU_MSG_SetOverclockFrequencyAllCores, ref result.args); 18 | } 19 | 20 | return base.Execute(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SMUCommands/SetFrequencySingleCore.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class SetFrequencySingleCore : BaseSMUCommand 4 | { 5 | public SetFrequencySingleCore(SMU smu) : base(smu) { } 6 | public CmdResult Execute(uint coreMask, uint frequency) 7 | { 8 | if (CanExecute()) 9 | { 10 | result.args[0] = coreMask | frequency & 0xfffff; 11 | // TODO: Add Manual OC mode 12 | // TODO: Add lo and hi frequency limits 13 | uint cmd = smu.Rsmu.SMU_MSG_SetOverclockFrequencyPerCore; 14 | if (cmd != 0) 15 | result.status = smu.SendRsmuCommand(cmd, ref result.args); 16 | else 17 | result.status = smu.SendMp1Command(smu.Mp1Smu.SMU_MSG_SetOverclockFrequencyPerCore, ref result.args); 18 | } 19 | 20 | return base.Execute(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SMUCommands/SetOcMode.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class SetOcMode : BaseSMUCommand 4 | { 5 | public SetOcMode(SMU smu) : base(smu) { } 6 | 7 | // TODO: Set OC vid based on current PState0 VID 8 | public CmdResult Execute(bool enabled, uint arg = 0U) 9 | { 10 | if (CanExecute()) 11 | { 12 | uint cmd = enabled ? smu.Rsmu.SMU_MSG_EnableOcMode : smu.Rsmu.SMU_MSG_DisableOcMode; 13 | result.args[0] = arg; 14 | 15 | if (cmd != 0) 16 | result.status = smu.SendRsmuCommand(cmd, ref result.args); 17 | else 18 | result.status = smu.SendMp1Command(enabled ? smu.Mp1Smu.SMU_MSG_EnableOcMode : smu.Mp1Smu.SMU_MSG_DisableOcMode, ref result.args); 19 | 20 | // Reset the scalar to 1.0 when disabling OC mode. Auto-reset seems to be broken for some SMU versions 21 | // The PBO Scalar is used to get the OC Mode (scalar = 0) 22 | if (!enabled && result.Success) 23 | result = new SetPBOScalar(smu).Execute(1); 24 | } 25 | 26 | return base.Execute(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SMUCommands/SetOverclockCpuVid.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class SetOverclockCpuVid : BaseSMUCommand 4 | { 5 | public SetOverclockCpuVid(SMU smuInstance) : base(smuInstance) { } 6 | 7 | public CmdResult Execute(uint vid) 8 | { 9 | if (CanExecute()) 10 | { 11 | result.args[0] = vid; 12 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_SetOverclockCpuVid, ref result.args); 13 | } 14 | return base.Execute(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SMUCommands/SetPBOScalar.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class SetPBOScalar : BaseSMUCommand 4 | { 5 | public SetPBOScalar(SMU smu) : base(smu) { } 6 | 7 | public CmdResult Execute(uint arg = 1) 8 | { 9 | if (CanExecute()) 10 | { 11 | result.args[0] = arg * 100; 12 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_SetPBOScalar, ref result.args); 13 | } 14 | 15 | return base.Execute(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SMUCommands/SetPsmMarginAllCores.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | // Set DLDO Psm margin for all cores 4 | // CO margin range seems to be from -30 to 30 5 | // Margin arg seems to be 16 bits (lowest 16 bits of the command arg) 6 | // [15-0] CO margin 7 | internal class SetPsmMarginAllCores : BaseSMUCommand 8 | { 9 | public SetPsmMarginAllCores(SMU smu) : base(smu) { } 10 | 11 | public override bool CanExecute() 12 | { 13 | return smu.Mp1Smu.SMU_MSG_SetAllDldoPsmMargin > 0 || smu.Rsmu.SMU_MSG_SetAllDldoPsmMargin > 0; 14 | } 15 | 16 | public CmdResult Execute(int margin) 17 | { 18 | if (CanExecute()) 19 | { 20 | result.args[0] = Utils.MakePsmMarginArg(margin); 21 | if (smu.Mp1Smu.SMU_MSG_SetAllDldoPsmMargin > 0) 22 | result.status = smu.SendMp1Command(smu.Mp1Smu.SMU_MSG_SetAllDldoPsmMargin, ref result.args); 23 | else 24 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_SetAllDldoPsmMargin, ref result.args); 25 | } 26 | 27 | return base.Execute(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SMUCommands/SetPsmMarginSingleCore.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | // Set DLDO Psm margin for a single core 4 | // CO margin range seems to be from -30 to 30 5 | // Margin arg seems to be 16 bits (lowest 16 bits of the command arg) 6 | // [31-28] ccd index 7 | // [27-24] ccx index (always 0 for Zen3 where each ccd has just one ccx) 8 | // [23-20] core index 9 | // [19-16] reserved? 10 | // [15-0] CO margin 11 | internal class SetPsmMarginSingleCore : BaseSMUCommand 12 | { 13 | public SetPsmMarginSingleCore(SMU smu) : base(smu) { } 14 | 15 | public override bool CanExecute() 16 | { 17 | return smu.Mp1Smu.SMU_MSG_SetDldoPsmMargin > 0 || smu.Rsmu.SMU_MSG_SetDldoPsmMargin > 0; 18 | } 19 | 20 | public CmdResult Execute(uint coreMask, int margin) 21 | { 22 | if (CanExecute()) 23 | { 24 | uint m = Utils.MakePsmMarginArg(margin); 25 | result.args[0] = (coreMask & 0xfff00000) | m; 26 | if (smu.Mp1Smu.SMU_MSG_SetDldoPsmMargin > 0) 27 | result.status = smu.SendMp1Command(smu.Mp1Smu.SMU_MSG_SetDldoPsmMargin, ref result.args); 28 | else 29 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_SetDldoPsmMargin, ref result.args); 30 | } 31 | 32 | return base.Execute(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SMUCommands/SetSmuLimit.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class SetSmuLimit : BaseSMUCommand 4 | { 5 | public SetSmuLimit(SMU smu) : base(smu) { } 6 | public CmdResult Execute(uint cmd, uint arg = 0U) 7 | { 8 | if (CanExecute()) 9 | { 10 | result.args[0] = arg * 1000; 11 | result.status = smu.SendRsmuCommand(cmd, ref result.args); 12 | } 13 | 14 | return base.Execute(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SMUCommands/SetToolsDramAddress.cs: -------------------------------------------------------------------------------- 1 | namespace ZenStates.Core.SMUCommands 2 | { 3 | internal class SetToolsDramAddress : BaseSMUCommand 4 | { 5 | public SetToolsDramAddress(SMU smu) : base(smu) { } 6 | public CmdResult Execute(uint arg = 0U) 7 | { 8 | if (CanExecute()) 9 | { 10 | result.args[0] = arg; 11 | result.status = smu.SendMp1Command(smu.Mp1Smu.SMU_MSG_SetToolsDramAddress, ref result.args); 12 | } 13 | 14 | return base.Execute(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SMUCommands/TransferTableToDram.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | 3 | namespace ZenStates.Core.SMUCommands 4 | { 5 | internal class TransferTableToDram : BaseSMUCommand 6 | { 7 | public TransferTableToDram(SMU smu) : base(smu) { } 8 | public override CmdResult Execute() 9 | { 10 | if (CanExecute()) 11 | { 12 | SendCommand(); 13 | 14 | // I was getting CMD_REJECTED_PREREQ for some reason, but hwinfo wass able to overcome this 15 | // Resending the command was enough to clear the status and to successfully pass from the second attempt 16 | // Add a sleep to give it a better chance 17 | if (result.status == SMU.Status.CMD_REJECTED_PREREQ) 18 | { 19 | Thread.Sleep(10); 20 | result.args = Utils.MakeCmdArgs(); 21 | SendCommand(); 22 | } 23 | } 24 | 25 | return base.Execute(); 26 | } 27 | 28 | private void SendCommand() 29 | { 30 | if (smu.SMU_TYPE == SMU.SmuType.TYPE_APU0 || smu.SMU_TYPE == SMU.SmuType.TYPE_APU1) 31 | { 32 | result.args[0] = 3; 33 | } 34 | result.status = smu.SendRsmuCommand(smu.Rsmu.SMU_MSG_TransferTableToDram, ref result.args); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SystemInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Management; 3 | using System.ServiceProcess; 4 | using static ZenStates.Core.Cpu; 5 | 6 | namespace ZenStates.Core 7 | { 8 | [Serializable] 9 | public class SystemInfo 10 | { 11 | private static CPUInfo cpuInfo; 12 | public SystemInfo(CPUInfo info, SMU smu) 13 | { 14 | cpuInfo = info; 15 | SmuVersion = smu.Version; 16 | SmuTableVersion = smu.TableVersion; 17 | 18 | try 19 | { 20 | ServiceController sc = new ServiceController("Winmgmt"); 21 | if (sc.Status != ServiceControllerStatus.Running) 22 | throw new ManagementException(@"Windows Management Instrumentation service is not running"); 23 | 24 | ManagementScope scope = new ManagementScope(@"root\cimv2"); 25 | scope.Connect(); 26 | 27 | if (!scope.IsConnected) 28 | throw new ManagementException(@"Failed to connect to root\cimv2"); 29 | 30 | ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_BaseBoard"); 31 | foreach (ManagementBaseObject obj in searcher.Get()) 32 | { 33 | MbVendor = ((string)obj["Manufacturer"]).Trim(); 34 | MbName = ((string)obj["Product"]).Trim(); 35 | } 36 | searcher.Dispose(); 37 | 38 | searcher = new ManagementObjectSearcher("SELECT * FROM Win32_BIOS"); 39 | foreach (ManagementBaseObject obj in searcher.Get()) 40 | { 41 | BiosVersion = ((string)obj["SMBIOSBIOSVersion"]).Trim(); 42 | } 43 | searcher.Dispose(); 44 | } 45 | catch (ManagementException ex) 46 | { 47 | Console.WriteLine("WMI: {0}", ex.Message); 48 | } 49 | } 50 | 51 | public string CpuName => cpuInfo.cpuName ?? "N/A"; 52 | public string CodeName => cpuInfo.codeName.ToString(); 53 | public uint CpuId => cpuInfo.cpuid; 54 | public uint BaseModel => cpuInfo.baseModel; 55 | public uint ExtendedModel => cpuInfo.extModel; 56 | public uint Model => cpuInfo.model; 57 | public uint Stepping => cpuInfo.stepping; 58 | // This is not working correctly, it needs mappings for each generation 59 | // public string PackageType => $"{cpuInfo.packageType} ({(int)cpuInfo.packageType})"; 60 | public int FusedCoreCount => (int)cpuInfo.topology.cores; 61 | public int PhysicalCoreCount => (int)cpuInfo.topology.physicalCores; 62 | public int NodesPerProcessor => (int)cpuInfo.topology.cpuNodes; 63 | public int Threads => (int)cpuInfo.topology.logicalCores; 64 | public bool SMT => (int)cpuInfo.topology.threadsPerCore > 1; 65 | // Disable for now, need revising 66 | // public int CCDCount => (int)cpuInfo.topology.ccds; 67 | // public int CCXCount => (int)cpuInfo.topology.ccxs; 68 | // public int NumCoresInCCX => (int)cpuInfo.topology.coresPerCcx; 69 | public string MbVendor { get; private set; } 70 | public string MbName { get; private set; } 71 | public string BiosVersion { get; private set; } 72 | public uint SmuVersion { get; private set; } 73 | public uint SmuTableVersion { get; private set; } 74 | public uint PatchLevel => cpuInfo.patchLevel; 75 | public string GetSmuVersionString() => SmuVersionToString(SmuVersion); 76 | 77 | public string GetCpuIdString() => CpuId.ToString("X8").TrimStart('0'); 78 | 79 | private static string SmuVersionToString(uint ver) 80 | { 81 | if ((ver & 0xFF000000) > 0) 82 | { 83 | return $"{(ver >> 24) & 0xff}.{(ver >> 16) & 0xff}.{(ver >> 8) & 0xff}.{ver & 0xff}"; 84 | } 85 | 86 | return $"{(ver >> 16) & 0xff}.{(ver >> 8) & 0xff}.{ver & 0xff}"; 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Utils.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using System; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | 9 | namespace ZenStates.Core 10 | { 11 | public static class Utils 12 | { 13 | public static bool Is64Bit => OpenHardwareMonitor.Hardware.OperatingSystem.Is64BitOperatingSystem; 14 | 15 | public static uint SetBits(uint val, int offset, int n, uint newVal) 16 | { 17 | return val & ~(((1U << n) - 1) << offset) | (newVal << offset); 18 | } 19 | 20 | public static uint SetBit(uint val, int offset) => SetBits(val, offset, 1, 1); 21 | 22 | public static uint ClearBit(uint val, int offset) => SetBits(val, offset, 1, 0); 23 | 24 | public static uint GetBits(uint val, int offset, int n) 25 | { 26 | return (val >> offset) & ~(~0U << n); 27 | } 28 | 29 | public static uint GetBit(uint value, int bitOffset) => GetBits(value, bitOffset, 1); 30 | 31 | public static uint BitSlice(uint val, int hi, int lo) 32 | { 33 | uint mask = (2U << hi - lo) - 1U; 34 | return val >> lo & mask; 35 | } 36 | 37 | public static uint CountSetBits(uint v) 38 | { 39 | uint result = 0; 40 | 41 | while (v > 0) 42 | { 43 | if ((v & 1) == 1) 44 | result++; 45 | 46 | v >>= 1; 47 | } 48 | 49 | return result; 50 | } 51 | 52 | // https://github.com/LibreHardwareMonitor/LibreHardwareMonitor/blob/master/LibreHardwareMonitorLib/Hardware/SMBios.cs#L918 53 | public static bool IsBitSet(byte b, int pos) 54 | { 55 | return (b & (1 << pos)) != 0; 56 | } 57 | 58 | public static string GetStringPart(uint val) 59 | { 60 | return val != 0 ? Convert.ToChar(val).ToString() : ""; 61 | } 62 | 63 | public static string IntToStr(uint val) 64 | { 65 | uint part1 = val & 0xff; 66 | uint part2 = val >> 8 & 0xff; 67 | uint part3 = val >> 16 & 0xff; 68 | uint part4 = val >> 24 & 0xff; 69 | 70 | return $"{GetStringPart(part1)}{GetStringPart(part2)}{GetStringPart(part3)}{GetStringPart(part4)}"; 71 | } 72 | 73 | public static double VidToVoltage(uint vid) 74 | { 75 | return 1.55 - vid * 0.00625; 76 | } 77 | 78 | public static double VidToVoltageSVI3(uint vid) 79 | { 80 | return Math.Round(0.245 + vid * 0.005, 3); 81 | } 82 | 83 | public static uint VoltageToVidSVI3(double targetVoltage) 84 | { 85 | if (targetVoltage < 0.245) 86 | return 0; 87 | return (uint)Math.Round((targetVoltage - 0.245) / 0.005); 88 | } 89 | 90 | private static bool CheckAllZero(ref T[] typedArray) 91 | { 92 | if (typedArray == null) 93 | return true; 94 | 95 | foreach (var value in typedArray) 96 | { 97 | if (Convert.ToUInt32(value) != 0) 98 | return false; 99 | } 100 | 101 | return true; 102 | } 103 | 104 | public static bool AllZero(byte[] arr) => CheckAllZero(ref arr); 105 | 106 | public static bool AllZero(int[] arr) => CheckAllZero(ref arr); 107 | 108 | public static bool AllZero(uint[] arr) => CheckAllZero(ref arr); 109 | 110 | public static bool AllZero(float[] arr) => CheckAllZero(ref arr); 111 | 112 | public static uint[] MakeCmdArgs(uint[] args, uint maxArgs = Constants.DEFAULT_MAILBOX_ARGS) 113 | { 114 | uint[] cmdArgs = new uint[maxArgs]; 115 | uint length = (uint)Math.Min(maxArgs, args.Length); 116 | 117 | for (int i = 0; i < length; i++) 118 | cmdArgs[i] = args[i]; 119 | 120 | return cmdArgs; 121 | } 122 | 123 | public static uint[] MakeCmdArgs(uint arg = 0, uint maxArgs = Constants.DEFAULT_MAILBOX_ARGS) 124 | { 125 | return MakeCmdArgs(new uint[] { arg }, maxArgs); 126 | } 127 | 128 | // CO margin range seems to be from -30 to 30 129 | // Margin arg seems to be 16 bits (lowest 16 bits of the command arg) 130 | // Update 01 Nov 2022 - the range is different on Raphael, -40 is successfully set 131 | public static uint MakePsmMarginArg(int margin) 132 | { 133 | // if (margin > 30) 134 | // margin = 30; 135 | // else if (margin < -30) 136 | // margin = -30; 137 | 138 | int offset = margin < 0 ? 0x100000 : 0; 139 | return Convert.ToUInt32(offset + margin) & 0xffff; 140 | } 141 | 142 | public static T ByteArrayToStructure(byte[] byteArray) where T : new() 143 | { 144 | if (byteArray == null) 145 | return default; 146 | 147 | T structure; 148 | GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned); 149 | try 150 | { 151 | structure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); 152 | } 153 | finally 154 | { 155 | handle.Free(); 156 | } 157 | return structure; 158 | } 159 | 160 | public static uint ReverseBytes(uint value) 161 | { 162 | return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 | 163 | (value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24; 164 | } 165 | 166 | public static string GetStringFromBytes(uint value) 167 | { 168 | byte[] bytes = BitConverter.GetBytes(value); 169 | // Array.Reverse(bytes); 170 | return System.Text.Encoding.ASCII.GetString(bytes).Replace("\0", " "); 171 | } 172 | 173 | public static string GetStringFromBytes(ulong value) 174 | { 175 | byte[] bytes = BitConverter.GetBytes(value); 176 | // Array.Reverse(bytes); 177 | return System.Text.Encoding.ASCII.GetString(bytes).Replace("\0", " "); 178 | } 179 | 180 | public static string GetStringFromBytes(byte[] value) 181 | { 182 | return System.Text.Encoding.ASCII.GetString(value).Replace("\0", " "); 183 | } 184 | 185 | /// Looks for the next occurrence of a sequence in a byte array 186 | /// Array that will be scanned 187 | /// Index in the array at which scanning will begin 188 | /// Sequence the array will be scanned for 189 | /// 190 | /// The index of the next occurrence of the sequence of -1 if not found 191 | /// 192 | public static int FindSequence(byte[] source, int start, byte[] pattern) 193 | { 194 | if (source == null || source.Length == 0 || pattern == null || pattern.Length == 0) 195 | return -1; 196 | 197 | if (pattern.Length > source.Length) 198 | return -1; 199 | 200 | if (start < 0 || start >= source.Length) 201 | return -1; 202 | 203 | int end = source.Length - pattern.Length; 204 | byte firstByte = pattern[0]; 205 | 206 | while (start <= end) 207 | { 208 | if (source[start] == firstByte) 209 | { 210 | int offset; 211 | for (offset = 1; offset < pattern.Length; offset++) 212 | { 213 | if (source[start + offset] != pattern[offset]) 214 | { 215 | break; 216 | } 217 | } 218 | 219 | if (offset == pattern.Length) 220 | return start; 221 | } 222 | 223 | start++; 224 | } 225 | 226 | return -1; 227 | } 228 | 229 | 230 | public static bool ArrayMembersEqual(float[] array1, float[] array2, int numElements) 231 | { 232 | if (array1 == null || array2 == null) 233 | return false; 234 | 235 | if (array1.Length < numElements || array2.Length < numElements) 236 | { 237 | // throw new ArgumentException("Arrays are not long enough to compare the specified number of elements."); 238 | Console.WriteLine("Arrays are not long enough to compare the specified number of elements."); 239 | return false; 240 | } 241 | 242 | for (int i = 0; i < numElements; i++) 243 | { 244 | if (array1[i] != array2[i]) 245 | { 246 | return false; 247 | } 248 | } 249 | 250 | return true; 251 | } 252 | 253 | public static bool PartialStringMatch(string str, string[] arr) 254 | { 255 | bool match = false; 256 | for (int i = 0; i < arr.Length; i++) 257 | { 258 | if (str.Contains(arr[i])) { match = true; break; } 259 | } 260 | return match; 261 | } 262 | 263 | public static float ToNanoseconds(uint value, float frequency) 264 | { 265 | if (frequency != 0) 266 | { 267 | float refiValue = Convert.ToSingle(value); 268 | float trefins = refiValue * 2000f / frequency; 269 | if (trefins > refiValue) trefins /= 2; 270 | return trefins; 271 | } 272 | return 0; 273 | } 274 | 275 | public static void RemoveRegistryKey(string keyPath) 276 | { 277 | try 278 | { 279 | using (var key = Registry.LocalMachine.OpenSubKey(keyPath, true)) 280 | { 281 | if (key != null) 282 | { 283 | Registry.LocalMachine.DeleteSubKeyTree(keyPath); 284 | Console.WriteLine($"Deleted registry key: HKEY_LOCAL_MACHINE\\{keyPath}"); 285 | } 286 | else 287 | { 288 | Console.WriteLine($"Registry key not found: HKEY_LOCAL_MACHINE\\{keyPath}"); 289 | } 290 | } 291 | } 292 | catch (Exception ex) 293 | { 294 | Console.WriteLine($"Failed to delete registry key: {ex.Message}"); 295 | } 296 | } 297 | 298 | public class CommandExecutionResult 299 | { 300 | public bool Success { get; set; } 301 | public string StandardOutput { get; set; } 302 | public string StandardError { get; set; } 303 | public int ExitCode { get; set; } 304 | public string State { get; set; } 305 | } 306 | 307 | public static CommandExecutionResult ExecuteCommand(string command) 308 | { 309 | var processInfo = new ProcessStartInfo("cmd.exe", "/c " + command) 310 | { 311 | CreateNoWindow = true, 312 | UseShellExecute = false, 313 | RedirectStandardOutput = true, 314 | RedirectStandardError = true 315 | }; 316 | 317 | var result = new CommandExecutionResult(); 318 | var standardOutput = new StringBuilder(); 319 | var standardError = new StringBuilder(); 320 | 321 | using (var process = Process.Start(processInfo)) 322 | { 323 | if (process == null) 324 | { 325 | result.Success = false; 326 | result.StandardError = "Failed to start process."; 327 | return result; 328 | } 329 | 330 | process.OutputDataReceived += (sender, e) => { if (e.Data != null) standardOutput.AppendLine(e.Data); }; 331 | process.BeginOutputReadLine(); 332 | process.ErrorDataReceived += (sender, e) => { if (e.Data != null) standardError.AppendLine(e.Data); }; 333 | process.BeginErrorReadLine(); 334 | process.WaitForExit(); 335 | 336 | result.Success = process.ExitCode == 0; 337 | result.StandardOutput = standardOutput.ToString(); 338 | result.StandardError = standardError.ToString(); 339 | result.ExitCode = process.ExitCode; 340 | 341 | // Parse the state from the standard output 342 | var stateMatch = Regex.Match(result.StandardOutput, @"STATE\s+:\s+\d+\s+(\w+)"); 343 | if (stateMatch.Success) 344 | { 345 | result.State = stateMatch.Groups[1].Value; 346 | } 347 | else 348 | { 349 | result.State = "Unknown"; 350 | } 351 | } 352 | 353 | return result; 354 | } 355 | 356 | public static bool DeleteFile(string filePath) 357 | { 358 | try 359 | { 360 | if (File.Exists(filePath)) 361 | { 362 | File.Delete(filePath); 363 | Console.WriteLine($"Deleted file: {filePath}"); 364 | } 365 | else 366 | { 367 | Console.WriteLine($"File not found: {filePath}"); 368 | } 369 | return true; 370 | } 371 | catch (Exception ex) 372 | { 373 | return false; 374 | } 375 | } 376 | 377 | public static bool HasDependentServices(string serviceName) 378 | { 379 | CommandExecutionResult result = ExecuteCommand($"sc.exe qc {serviceName}"); 380 | string output = result.StandardOutput; 381 | bool hasDependents = false; 382 | foreach (var line in output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)) 383 | { 384 | if (line.Trim().StartsWith("DEPENDENCIES")) 385 | { 386 | string dependencies = line.Split(new[] { ':' }, 2)[1].Trim(); 387 | if (!string.IsNullOrEmpty(dependencies)) 388 | { 389 | hasDependents = true; 390 | Console.WriteLine($"Dependent services: {dependencies}"); 391 | } 392 | } 393 | } 394 | return hasDependents; 395 | } 396 | 397 | public static int GetServiceProcessId(string serviceName) 398 | { 399 | CommandExecutionResult result = ExecuteCommand($"sc.exe queryex {serviceName}"); 400 | string output = result.StandardOutput; 401 | 402 | foreach (var line in output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)) 403 | { 404 | if (line.Trim().StartsWith("PID")) 405 | { 406 | if (int.TryParse(line.Split(':')[1].Trim(), out int pid)) 407 | { 408 | return pid; 409 | } 410 | } 411 | } 412 | return -1; 413 | } 414 | 415 | public static void KillProcess(int processId) 416 | { 417 | try 418 | { 419 | Process process = Process.GetProcessById(processId); 420 | process.Kill(); 421 | process.WaitForExit(); 422 | } 423 | catch (Exception ex) 424 | { 425 | Console.WriteLine($"Failed to kill process {processId}: {ex.Message}"); 426 | } 427 | } 428 | 429 | public static bool ServiceExists(string serviceName) 430 | { 431 | CommandExecutionResult result = ExecuteCommand($"sc query {serviceName}"); 432 | string output = result.StandardOutput; 433 | 434 | return !output.Contains("FAILED 1060"); 435 | } 436 | } 437 | } 438 | -------------------------------------------------------------------------------- /WMI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Management; 4 | using System.ServiceProcess; 5 | using static System.Management.ManagementObjectCollection; 6 | 7 | namespace ZenStates.Core 8 | { 9 | public static class WMI 10 | { 11 | public static object TryGetProperty(ManagementObject wmiObj, string propertyName) 12 | { 13 | object retval = null; 14 | try 15 | { 16 | retval = wmiObj.GetPropertyValue(propertyName); 17 | } 18 | catch (ManagementException ex) 19 | { 20 | Console.WriteLine(ex.Message); 21 | } 22 | 23 | return retval; 24 | } 25 | 26 | //root\wmi 27 | public static ManagementScope Connect(string scope) 28 | { 29 | try 30 | { 31 | var sc = new ServiceController("Winmgmt"); 32 | if (sc.Status != ServiceControllerStatus.Running) 33 | throw new ManagementException(@"Windows Management Instrumentation service is not running"); 34 | 35 | ManagementScope mScope = new ManagementScope($@"{scope}"); 36 | mScope.Connect(); 37 | 38 | if (mScope.IsConnected) 39 | return mScope; 40 | else 41 | throw new ManagementException($@"Failed to connect to {scope}"); 42 | } 43 | catch (ManagementException ex) 44 | { 45 | Console.WriteLine(@"WMI: {0}", ex.Message); 46 | throw; 47 | } 48 | } 49 | 50 | public static ManagementObject Query(string scope, string wmiClass) 51 | { 52 | try 53 | { 54 | using (var searcher = new ManagementObjectSearcher($"{scope}", $"SELECT * FROM {wmiClass}")) 55 | { 56 | ManagementObjectEnumerator enumerator = searcher.Get().GetEnumerator(); 57 | if (enumerator.MoveNext()) 58 | return enumerator.Current as ManagementObject; 59 | } 60 | } 61 | catch (Exception ex) 62 | { 63 | Console.WriteLine(ex.Message); 64 | } 65 | 66 | return null; 67 | } 68 | 69 | public static List GetWmiNamespaces(string root) 70 | { 71 | List namespaces = new List(); 72 | try 73 | { 74 | ManagementClass nsClass = 75 | new ManagementClass(new ManagementScope(root), new ManagementPath("__namespace"), null); 76 | foreach (var obj in nsClass.GetInstances()) 77 | { 78 | var ns = (ManagementObject)obj; 79 | string namespaceName = root + "\\" + ns["Name"]; 80 | namespaces.Add(namespaceName); 81 | namespaces.AddRange(GetWmiNamespaces(namespaceName)); 82 | } 83 | 84 | namespaces.Sort(StringComparer.OrdinalIgnoreCase); 85 | } 86 | catch (Exception ex) 87 | { 88 | Console.WriteLine(ex.Message); 89 | } 90 | 91 | return namespaces; 92 | } 93 | 94 | public static List GetClassNamesWithinWmiNamespace(string wmiNamespaceName) 95 | { 96 | List classNames = new List(); 97 | try 98 | { 99 | ManagementObjectSearcher searcher = new ManagementObjectSearcher 100 | (new ManagementScope(wmiNamespaceName), 101 | new WqlObjectQuery("SELECT * FROM meta_class")); 102 | ManagementObjectCollection objectCollection = searcher.Get(); 103 | foreach (var obj in objectCollection) 104 | { 105 | var wmiClass = (ManagementClass)obj; 106 | string stringified = wmiClass.ToString(); 107 | string[] parts = stringified.Split(':'); 108 | classNames.Add(parts[1]); 109 | } 110 | 111 | classNames.Sort(StringComparer.OrdinalIgnoreCase); 112 | } 113 | catch (Exception ex) 114 | { 115 | Console.WriteLine(ex.Message); 116 | } 117 | 118 | return classNames; 119 | } 120 | 121 | public static string GetInstanceName(string scope, string wmiClass) 122 | { 123 | using (ManagementObject queryObject = Query(scope, wmiClass)) 124 | { 125 | string name = ""; 126 | 127 | if (queryObject == null) 128 | return name; 129 | 130 | try 131 | { 132 | var obj = TryGetProperty(queryObject, "InstanceName"); 133 | if (obj != null) name = obj.ToString(); 134 | } 135 | catch 136 | { 137 | // ignored 138 | } 139 | 140 | return name; 141 | } 142 | } 143 | 144 | public static ManagementBaseObject InvokeMethod(ManagementObject mo, string methodName, string inParamName, uint arg) 145 | { 146 | try 147 | { 148 | // Obtain in-parameters for the method 149 | ManagementBaseObject inParams = mo.GetMethodParameters($"{methodName}"); 150 | 151 | // Add the input parameters. 152 | if (inParams != null) 153 | inParams[$"{inParamName}"] = arg; 154 | 155 | // Execute the method and obtain the return values. 156 | ManagementBaseObject outParams = mo.InvokeMethod($"{methodName}", inParams, null); 157 | 158 | return outParams; 159 | } 160 | catch (ManagementException) 161 | { 162 | return null; 163 | } 164 | } 165 | 166 | public static ManagementBaseObject InvokeMethodAndGetValue(ManagementObject mo, string methodName, string propName, 167 | string inParamName, uint arg) 168 | { 169 | try 170 | { 171 | ManagementBaseObject outParams = InvokeMethod(mo, methodName, inParamName, arg); 172 | return (ManagementBaseObject)outParams?.Properties[$"{propName}"].Value; 173 | } 174 | catch (Exception ex) 175 | { 176 | Console.WriteLine(ex.Message); 177 | return null; 178 | } 179 | } 180 | 181 | public static byte[] RunCommand(ManagementObject mo, uint commandID, uint commandArg = 0x0) 182 | { 183 | try 184 | { 185 | // Obtain in-parameters for the method 186 | ManagementBaseObject inParams = mo.GetMethodParameters("RunCommand"); 187 | 188 | // Add the input parameters. 189 | byte[] buffer = new byte[8]; 190 | 191 | var cmd = BitConverter.GetBytes(commandID); 192 | var arg = BitConverter.GetBytes(commandArg); 193 | 194 | Buffer.BlockCopy(cmd, 0, buffer, 0, 4); 195 | Buffer.BlockCopy(arg, 0, buffer, 4, 4); 196 | 197 | inParams["Inbuf"] = buffer; 198 | 199 | // Execute the method and obtain the return values. 200 | ManagementBaseObject outParams = mo.InvokeMethod("RunCommand", inParams, null); 201 | 202 | // return outParam 203 | ManagementBaseObject pack = (ManagementBaseObject)outParams?.Properties["Outbuf"].Value; 204 | return (byte[])pack?.GetPropertyValue("Result"); 205 | } 206 | catch (ManagementException ex) 207 | { 208 | Console.WriteLine(ex.Message); 209 | return null; 210 | } 211 | } 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /WinRing0.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irusanov/ZenStates-Core/6ff1ac847d8c7410e4eef9a1bdbedc8d7ed1a7e4/WinRing0.sys -------------------------------------------------------------------------------- /WinRing0x64.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irusanov/ZenStates-Core/6ff1ac847d8c7410e4eef9a1bdbedc8d7ed1a7e4/WinRing0x64.sys -------------------------------------------------------------------------------- /ZenStates-Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | ZenStates.Core 4 | net20;netstandard2.1;net8.0-windows 5 | ZenStates.Core 6 | irusanov 7 | ZenStates.Core 8 | Copyright © 2025 9 | 1.75.0 10 | 1.75.0 11 | bin\$(Configuration)\ 12 | true 13 | true 14 | 15 | 16 | full 17 | 18 | 19 | pdbonly 20 | 21 | 22 | 23 | none 24 | 25 | 26 | 4 27 | True 28 | 29 | 30 | 4 31 | True 32 | 33 | 34 | 4 35 | True 36 | 37 | 38 | 4 39 | True 40 | 41 | 42 | True 43 | 44 | 45 | True 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | Always 72 | 73 | 74 | Always 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 5.0.0 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /ZenStates-Core.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30717.126 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZenStates-Core", "ZenStates-Core.csproj", "{D2D449E1-8701-442F-B440-37188F8D2380}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {D2D449E1-8701-442F-B440-37188F8D2380}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {D2D449E1-8701-442F-B440-37188F8D2380}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {D2D449E1-8701-442F-B440-37188F8D2380}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {D2D449E1-8701-442F-B440-37188F8D2380}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {312186D3-D673-4E17-A3DE-326B34348E8D} 24 | EndGlobalSection 25 | EndGlobal 26 | --------------------------------------------------------------------------------