Hi,
While testing the tool on macOS Golden Gate, I noticed battery maintain and manual charging controls stopped functioning because of low-level changes Apple made to the SMC interface.
I investigated how the new OS manages battery limits and wanted to share the findings here in case it helps with updating the backend.
What Fails Currently
smc -k CH0B -r returns CH0B [ ] no data. The legacy register keys (CH0B, CH0C, CH0I) are no longer populated.
- The active charging register is now
CHIB ([ui8]). However, writing to it (smc -k CHIB -w 01) fails with:
Error: SMCWriteKey() = e00002c1 (kIOReturnNotPrivileged)
macOS now enforces SIP entitlements (com.apple.private.applesmc.user-client-access) on AppleSMCClient. Even running as root via sudo is blocked by the kernel.
How macOS Golden Gate Handles Charging Limits Natively
Apple moved charge limiting into powerd and PowerUI.framework (Manual Charge Limit / MCL) via XPC (com.apple.powerui.smartChargeManager).
This interface is accessible in userspace without sudo or SIP disablement through PowerUISmartChargeClient:
Class clientClass = objc_getClass("PowerUISmartChargeClient");
id client = [[clientClass alloc] initWithClientName:@"battery-cli"];
// Enable limit (native supported values: 80, 85, 90, 95, 100)
[client enableMCL:&err];
[client setMCLLimit:80 error:&err];
// Disable limit (restores 100% charging)
[client disableMCL:&err];
When set, powerd registers a ChargeCtrlPolicy in /Library/Preferences/com.apple.powerd.charging.plist with:
reason: manualChargeLimit
soclimit: 80
drain: true
isEndOfCharge: true
The PMU then cuts charging current to 0 mA and runs the laptop on adapter passthrough.
Note on Periodic Calibration (ChargingUpForGauging)
During testing with this interface, macOS may occasionally charge to 100% before holding at 80%, logging:
SOC limit policy suspend due to mitigation active:1
ChargingUpForGauging (mode: 0)
This is Apple's periodic gas gauge calibration cycle. Once the battery reaches 100% and finishes balancing, powerd clears the mitigation flag and drops back to 80% automatically.
Conclusion
If the project plans to support macOS Golden Gate, adding a fallback path that calls PowerUISmartChargeClient when CH0B returns no data or when SMC writes fail with e00002c1 looks like the cleanest native solution.
Hi,
While testing the tool on macOS Golden Gate, I noticed
battery maintainand manual charging controls stopped functioning because of low-level changes Apple made to the SMC interface.I investigated how the new OS manages battery limits and wanted to share the findings here in case it helps with updating the backend.
What Fails Currently
smc -k CH0B -rreturnsCH0B [ ] no data. The legacy register keys (CH0B,CH0C,CH0I) are no longer populated.CHIB([ui8]). However, writing to it (smc -k CHIB -w 01) fails with:com.apple.private.applesmc.user-client-access) onAppleSMCClient. Even running as root via sudo is blocked by the kernel.How macOS Golden Gate Handles Charging Limits Natively
Apple moved charge limiting into
powerdandPowerUI.framework(Manual Charge Limit / MCL) via XPC (com.apple.powerui.smartChargeManager).This interface is accessible in userspace without sudo or SIP disablement through
PowerUISmartChargeClient:When set,
powerdregisters aChargeCtrlPolicyin/Library/Preferences/com.apple.powerd.charging.plistwith:reason:manualChargeLimitsoclimit:80drain:trueisEndOfCharge:trueThe PMU then cuts charging current to 0 mA and runs the laptop on adapter passthrough.
Note on Periodic Calibration (ChargingUpForGauging)
During testing with this interface, macOS may occasionally charge to 100% before holding at 80%, logging:
This is Apple's periodic gas gauge calibration cycle. Once the battery reaches 100% and finishes balancing,
powerdclears the mitigation flag and drops back to 80% automatically.Conclusion
If the project plans to support macOS Golden Gate, adding a fallback path that calls
PowerUISmartChargeClientwhenCH0Breturns no data or when SMC writes fail withe00002c1looks like the cleanest native solution.