Page MenuHomeFreeBSD

asmc: add raw SMC key read/write interface
AcceptedPublic

Authored by guest-seuros on Dec 31 2025, 6:54 PM.
Tags
None
Referenced Files
Unknown Object (File)
Fri, Mar 20, 6:57 AM
Unknown Object (File)
Sun, Mar 15, 5:29 PM
Unknown Object (File)
Wed, Mar 11, 9:54 AM
Unknown Object (File)
Mon, Mar 9, 12:55 PM
Unknown Object (File)
Wed, Mar 4, 12:25 PM
Unknown Object (File)
Sun, Mar 1, 8:41 AM
Unknown Object (File)
Wed, Feb 25, 2:36 AM
Unknown Object (File)
Mon, Feb 23, 3:25 AM
Subscribers

Details

Summary

This patch adds a debugging interface to read and write arbitrary Apple SMC keys by name through sysctl, enabling hardware exploration and control of undocumented features.

The interface provides four sysctls under dev.asmc.0.raw.*:

  • key - Set the 4-character SMC key name (e.g., "AUPO")
  • value - Read/write key value as a hex string
  • len - Auto-detected key value length (can be overridden)
  • type - Read-only 4-character type string (e.g., "ui8", "flt")

Implementation includes a new asmc_key_getinfo() function using SMC command 0x13 to query key metadata. The interface automatically detects key lengths and types, uses hex string encoding for arbitrary binary values, and is safe for concurrent access via CTLFLAG_NEEDGIANT.

This interface was essential for discovering that the AUPO key enables Wake-on-LAN from S5 state, and for mapping all 297 SMC keys on Mac Mini 5,1.

Test Plan

Testing this is a little tricky :

sysctl dev.asmc.0.raw.key=AUPO
sysctl dev.asmc.0.raw.value # Returns "00" or "01"
sysctl dev.asmc.0.raw.type # Returns "ui8 "

sysctl dev.asmc.0.raw.value=01 # Enable WoL
sysctl dev.asmc.0.raw.value=00 # Disable WoL

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 71417
Build 68300: arc lint + arc unit

Event Timeline

guest-seuros created this revision.
sys/dev/asmc/asmc.c
1239

I see this pattern was copied from elsewhere, but it'd still be nice to have a proper loop.

Are the retries actually needed?

1260

Should this be documented in the asmc.4 man page?

1305

This line should be wrapped.

1310

The formatting can be handled with sysctl -x. Should we just provide the raw bytes and let userspace handle formatting?

1341

Missing parens around the return value.

1350

Missing parens around the return value.

sys/dev/asmc/asmc.c
1310
$ sysctl dev.asmc.0.raw.key=AUPO
$ sysctl -x dev.asmc.0.raw.value
dev.asmc.0.raw.value: Format: Length:1 Dump:0x01

However, sysctl -x only handles formatting for output.
For writing, the sysctl tool does not support opaque types at all:

$ sysctl -w dev.asmc.0.raw.value=00
sysctl: oid 'dev.asmc.0.raw.value' is type 5, cannot set that

The hex string approach allowed both.

I'm open to any approach, i already mapped most of this hardware.

markj added inline comments.
sys/dev/asmc/asmc.c
1234

error is never used, you can just return 0 at the end of the function.

This revision is now accepted and ready to land.Jan 9 2026, 2:22 PM
guest-seuros edited the test plan for this revision. (Show Details)

Make dev.asmc.*.raw.len read-only to prevent user overrides

This revision now requires review to proceed.Feb 4 2026, 1:34 AM

I think this should actually be behind another build option.

From what I've read, depending on how the user manipulates an SMC controller, they could basically brick the controller, and the system by proxy.

sys/dev/asmc/asmc.c
1310

The formatting can be handled with sysctl -x. Should we just provide the raw bytes and let userspace handle formatting?

+1. Let userspace handle the formatting.

Address review feedback: gate raw interface behind ASMC_DEBUG, fix return parens in len/type sysctls, wrap long line in value sysctl, match retry loop style with asmc_key_read, document in asmc.4

sys/dev/asmc/asmc.c
1408

Is this supposed to be checking hexbuf[0]?

sys/dev/asmc/asmc.c
1408

raw.value requires a key to be selected first via dev.asmc.X.raw.key.
sc->sc_rawkey[0] == '\0' indicates that no key has been configured yet.

Trying to write to the SMC without a valid key could lead to undefined behavior, so the handler rejects the write with EINVAL until a key is selected.

If this confused you, it will confuse my future self as well, so I will add a clarifying comment in the code i have locally.

Thanks for the review

markj added inline comments.
sys/dev/asmc/asmc.c
1408

A comment would be good. I think I figured this out the first time I read through the patch, but forgot when I skimmed it again.

This revision is now accepted and ready to land.Sun, Mar 15, 1:50 AM
sys/dev/asmc/asmc.c
1234

Agreed: the entire block is tautologically false right now (this would result in a "set but unused" failure with gcc). error should be caught from the asmc_* calls and bubbled up.

1322

This would be better/less prone to future out-of-bounds error issues.

1331

The retry count should be a preprocessor value (at the very least) and should be configurable via sysctl(9). I've found repeated failures due to bunk retries to be noisy when probing non-existent sensor when ASMC_DEBUG is enabled.

1332–1333

This message's value seems a bit dubious. What would you like to communicate to the end-user?

1361
1400

What do the magic numbers represent? Could they be represented by well-named constants instead?

1404
sys/dev/asmc/asmcvar.h
60

Could this please be made into a constant?

Address review: replace magic numbers with constants (ASMC_CMDGETINFO, ASMC_STATUS_AWAIT_DATA, ASMC_KEYLEN, ASMC_MAXRETRIES), fix asmc_key_dump error handling, add return parens, wrap long lines, add comments

This revision now requires review to proceed.Sun, Mar 15, 4:58 PM
This revision is now accepted and ready to land.Fri, Mar 20, 2:48 AM