Skip to content

Findings on macOS Golden Gate: SMC key deprecation (CH0B/CH0C) and transition to PowerUI #474

Description

@alphastar-avi

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

  1. smc -k CH0B -r returns CH0B [ ] no data. The legacy register keys (CH0B, CH0C, CH0I) are no longer populated.
  2. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions