-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathverify_live.swift
More file actions
114 lines (103 loc) · 3.87 KB
/
verify_live.swift
File metadata and controls
114 lines (103 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import Foundation
import IOKit
extension String {
var fourCharCode: UInt32 {
var result: UInt32 = 0
for char in self.utf8.prefix(4) {
result = (result << 8) | UInt32(char)
}
return result
}
}
class SMCVerifier {
private var connection: io_connect_t = 0
func open() -> Bool {
let service = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("AppleSMC"))
guard service != 0 else { return false }
let result = IOServiceOpen(service, mach_task_self_, 0, &connection)
IOObjectRelease(service)
return result == kIOReturnSuccess
}
func close() {
if connection != 0 {
IOServiceClose(connection)
connection = 0
}
}
func getInfo(_ key: String) -> (type: String, size: UInt32)? {
var input = SMCParamStruct()
var output = SMCParamStruct()
input.key = key.fourCharCode
input.data8 = UInt8(kSMCGetKeyInfo)
var outputSize = MemoryLayout<SMCParamStruct>.stride
let result = IOConnectCallStructMethod(connection, UInt32(kSMCHandleYPCEvent), &input, MemoryLayout<SMCParamStruct>.stride, &output, &outputSize)
if result == kIOReturnSuccess && output.result == 0 {
let t = typeStr(output.keyInfo.dataType)
return (t, output.keyInfo.dataSize)
}
return nil
}
func readRaw(_ key: String, size: UInt32) -> [UInt8]? {
var input = SMCParamStruct()
var output = SMCParamStruct()
input.key = key.fourCharCode
input.keyInfo.dataSize = size
input.data8 = UInt8(kSMCReadKey)
var outputSize = MemoryLayout<SMCParamStruct>.stride
let result = IOConnectCallStructMethod(connection, UInt32(kSMCHandleYPCEvent), &input, MemoryLayout<SMCParamStruct>.stride, &output, &outputSize)
if result == kIOReturnSuccess && output.result == 0 {
var bytes = [UInt8]()
withUnsafePointer(to: &output.bytes) { pointer in
let boundPtr = UnsafeRawPointer(pointer).bindMemory(to: UInt8.self, capacity: 32)
for i in 0..<Int(size) {
bytes.append(boundPtr[i])
}
}
return bytes
}
return nil
}
func typeStr(_ type: UInt32) -> String {
let bytes = [
UInt8((type >> 24) & 0xFF),
UInt8((type >> 16) & 0xFF),
UInt8((type >> 8) & 0xFF),
UInt8(type & 0xFF)
]
return String(bytes: bytes, encoding: .ascii) ?? "????"
}
func verifyOnce() {
let keys = ["B0AC", "B0AV", "PSTR", "PDTR", "B0RM"]
for key in keys {
if let info = getInfo(key), let bytes = readRaw(key, size: info.size) {
var val = ""
if info.size == 2 {
let be = Int(UInt16(bytes[0]) << 8 | UInt16(bytes[1]))
let le = Int(UInt16(bytes[1]) << 8 | UInt16(bytes[0]))
let s_be = Int(Int16(bitPattern: UInt16(be)))
let s_le = Int(Int16(bitPattern: UInt16(le)))
val = "BE:\(be) LE:\(le) S_BE:\(s_be) S_LE:\(s_le)"
} else if info.size == 4 {
if info.type == "flt " {
val = "Float: \(bytes.withUnsafeBytes { $0.load(as: Float.self) })"
} else {
val = "Raw: \(bytes)"
}
}
print("\(key) [\(info.type)]: \(val)")
}
}
}
}
let verifier = SMCVerifier()
if verifier.open() {
print("--- Polling live stats every 2 seconds (Ctrl+C to stop) ---")
for _ in 1...5 {
verifier.verifyOnce()
print("----------")
Thread.sleep(forTimeInterval: 2.0)
}
verifier.close()
} else {
print("Failed to open SMC")
}