Page MenuHomeFreeBSD

D54441.id169373.diff
No OneTemporary

D54441.id169373.diff

diff --git a/share/man/man4/asmc.4 b/share/man/man4/asmc.4
--- a/share/man/man4/asmc.4
+++ b/share/man/man4/asmc.4
@@ -23,7 +23,7 @@
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd April 2, 2019
+.Dd January 8, 2026
.Dt ASMC 4
.Os
.Sh NAME
@@ -110,6 +110,44 @@
respectively.
.Pp
All values are in RPM.
+.Sh RAW SMC KEY ACCESS
+The
+.Va dev.asmc.%d.raw
+sysctl tree provides direct access to arbitrary SMC keys for debugging
+and hardware exploration.
+This interface enables reading and writing any SMC key by name,
+allowing discovery of undocumented sensors and hardware controls.
+.Pp
+To use the raw SMC interface:
+.Bl -enum -offset indent
+.It
+Set the desired 4-character SMC key name:
+.Bd -literal -offset indent
+sysctl dev.asmc.0.raw.key=AUPO
+.Ed
+.It
+Read the key value as a hexadecimal string:
+.Bd -literal -offset indent
+sysctl dev.asmc.0.raw.value
+.Ed
+.It
+Write a new value as a hexadecimal string:
+.Bd -literal -offset indent
+sysctl dev.asmc.0.raw.value=01
+.Ed
+.El
+.Pp
+The key type and length are automatically detected when setting a key name.
+The
+.Va dev.asmc.%d.raw.len
+and
+.Va dev.asmc.%d.raw.type
+sysctls provide the detected length and 4-character type code.
+.Pp
+.Sy Warning :
+Writing incorrect values to SMC keys can cause system instability or
+hardware damage.
+This interface is intended for advanced users and developers only.
.Sh SUDDEN MOTION SENSOR
The Sudden Motion Sensor (SMS for short) is a device that detects
laptop movement and notifies the operating system via an interrupt.
diff --git a/sys/dev/asmc/asmc.c b/sys/dev/asmc/asmc.c
--- a/sys/dev/asmc/asmc.c
+++ b/sys/dev/asmc/asmc.c
@@ -109,6 +109,13 @@
static int asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS);
static int asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS);
+/* Raw key access */
+static int asmc_key_getinfo(device_t, const char *, uint8_t *, char *);
+static int asmc_raw_key_sysctl(SYSCTL_HANDLER_ARGS);
+static int asmc_raw_value_sysctl(SYSCTL_HANDLER_ARGS);
+static int asmc_raw_len_sysctl(SYSCTL_HANDLER_ARGS);
+static int asmc_raw_type_sysctl(SYSCTL_HANDLER_ARGS);
+
struct asmc_model {
const char *smc_model; /* smbios.system.product env var. */
const char *smc_desc; /* driver description */
@@ -716,6 +723,41 @@
"Keyboard backlight brightness control");
}
+ /*
+ * Raw SMC key access for debugging.
+ */
+ sc->sc_raw_tree = SYSCTL_ADD_NODE(sysctlctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+ "raw", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Raw SMC key access");
+
+ SYSCTL_ADD_PROC(sysctlctx,
+ SYSCTL_CHILDREN(sc->sc_raw_tree),
+ OID_AUTO, "key",
+ CTLTYPE_STRING | CTLFLAG_RW,
+ dev, 0, asmc_raw_key_sysctl, "A",
+ "SMC key name (4 chars)");
+
+ SYSCTL_ADD_PROC(sysctlctx,
+ SYSCTL_CHILDREN(sc->sc_raw_tree),
+ OID_AUTO, "value",
+ CTLTYPE_STRING | CTLFLAG_RW,
+ dev, 0, asmc_raw_value_sysctl, "A",
+ "SMC key value (hex string)");
+
+ SYSCTL_ADD_PROC(sysctlctx,
+ SYSCTL_CHILDREN(sc->sc_raw_tree),
+ OID_AUTO, "len",
+ CTLTYPE_U8 | CTLFLAG_RW,
+ dev, 0, asmc_raw_len_sysctl, "CU",
+ "SMC key value length");
+
+ SYSCTL_ADD_PROC(sysctlctx,
+ SYSCTL_CHILDREN(sc->sc_raw_tree),
+ OID_AUTO, "type",
+ CTLTYPE_STRING | CTLFLAG_RD,
+ dev, 0, asmc_raw_type_sysctl, "A",
+ "SMC key type (4 chars)");
+
if (model->smc_sms_x == NULL)
goto nosms;
@@ -1151,6 +1193,162 @@
}
#endif
+/*
+ * Get key info (length and type) from SMC using command 0x13.
+ * Returns 0 on success, -1 on failure.
+ * If len is non-NULL, stores the key's value length.
+ * If type is non-NULL, stores the 4-char type string (must be at least 5 bytes).
+ */
+static int
+asmc_key_getinfo(device_t dev, const char *key, uint8_t *len, char *type)
+{
+ struct asmc_softc *sc = device_get_softc(dev);
+ uint8_t info[6];
+ int i, error;
+
+ mtx_lock_spin(&sc->sc_mtx);
+
+ if (asmc_command(dev, 0x13)) {
+ mtx_unlock_spin(&sc->sc_mtx);
+ return (-1);
+ }
+
+ for (i = 0; i < 4; i++) {
+ ASMC_DATAPORT_WRITE(sc, key[i]);
+ if (asmc_wait(dev, 0x04)) {
+ mtx_unlock_spin(&sc->sc_mtx);
+ return (-1);
+ }
+ }
+
+ ASMC_DATAPORT_WRITE(sc, 6);
+
+ for (i = 0; i < 6; i++) {
+ if (asmc_wait(dev, 0x05)) {
+ mtx_unlock_spin(&sc->sc_mtx);
+ return (-1);
+ }
+ info[i] = ASMC_DATAPORT_READ(sc);
+ }
+
+ error = 0;
+ mtx_unlock_spin(&sc->sc_mtx);
+
+ if (error == 0) {
+ if (len != NULL)
+ *len = info[0];
+ if (type != NULL) {
+ for (i = 0; i < 4; i++)
+ type[i] = info[i + 1];
+ type[4] = '\0';
+ }
+ }
+ return (error);
+}
+
+/*
+ * Raw SMC key access sysctls - enables reading/writing any SMC key by name
+ * Usage:
+ * sysctl dev.asmc.0.raw.key=AUPO # Set key, auto-detects length
+ * sysctl dev.asmc.0.raw.value # Read current value (hex)
+ * sysctl dev.asmc.0.raw.value=01 # Write new value (hex)
+ */
+static int
+asmc_raw_key_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev = (device_t) arg1;
+ struct asmc_softc *sc = device_get_softc(dev);
+ char newkey[5];
+ uint8_t keylen;
+ int error;
+
+ strlcpy(newkey, sc->sc_rawkey, sizeof(newkey));
+ error = sysctl_handle_string(oidp, newkey, sizeof(newkey), req);
+ if (error || req->newptr == NULL)
+ return (error);
+
+ if (strlen(newkey) != 4)
+ return (EINVAL);
+
+ /* Get key info to auto-detect length and type */
+ if (asmc_key_getinfo(dev, newkey, &keylen, sc->sc_rawtype) != 0)
+ return (ENOENT);
+
+ if (keylen > ASMC_MAXVAL)
+ keylen = ASMC_MAXVAL;
+
+ strlcpy(sc->sc_rawkey, newkey, sizeof(sc->sc_rawkey));
+ sc->sc_rawlen = keylen;
+ memset(sc->sc_rawval, 0, sizeof(sc->sc_rawval));
+
+ /* Read the key value */
+ asmc_key_read(dev, sc->sc_rawkey, sc->sc_rawval, sc->sc_rawlen);
+
+ return (0);
+}
+
+static int
+asmc_raw_value_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev = (device_t) arg1;
+ struct asmc_softc *sc = device_get_softc(dev);
+ char hexbuf[ASMC_MAXVAL * 2 + 1];
+ int error, i;
+
+ /* Refresh from SMC */
+ if (sc->sc_rawkey[0] != '\0') {
+ asmc_key_read(dev, sc->sc_rawkey, sc->sc_rawval,
+ sc->sc_rawlen > 0 ? sc->sc_rawlen : ASMC_MAXVAL);
+ }
+
+ /* Format as hex string */
+ for (i = 0; i < sc->sc_rawlen && i < ASMC_MAXVAL; i++)
+ snprintf(hexbuf + i * 2, 3, "%02x", sc->sc_rawval[i]);
+ hexbuf[i * 2] = '\0';
+
+ error = sysctl_handle_string(oidp, hexbuf, sizeof(hexbuf), req);
+ if (error || req->newptr == NULL)
+ return (error);
+
+ /* Parse hex and write */
+ if (sc->sc_rawkey[0] == '\0')
+ return (EINVAL);
+
+ memset(sc->sc_rawval, 0, sizeof(sc->sc_rawval));
+ for (i = 0; i < sc->sc_rawlen && hexbuf[i * 2] &&
+ hexbuf[i * 2 + 1]; i++) {
+ unsigned int val;
+ char tmp[3] = { hexbuf[i * 2], hexbuf[i * 2 + 1], 0 };
+ if (sscanf(tmp, "%02x", &val) == 1)
+ sc->sc_rawval[i] = (uint8_t)val;
+ }
+
+ if (asmc_key_write(dev, sc->sc_rawkey, sc->sc_rawval,
+ sc->sc_rawlen) != 0)
+ return (EIO);
+
+ return (0);
+}
+
+static int
+asmc_raw_len_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev = (device_t) arg1;
+ struct asmc_softc *sc = device_get_softc(dev);
+
+ return (sysctl_handle_8(oidp, &sc->sc_rawlen, 0, req));
+}
+
+static int
+asmc_raw_type_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev = (device_t) arg1;
+ struct asmc_softc *sc = device_get_softc(dev);
+
+ return (sysctl_handle_string(oidp, sc->sc_rawtype,
+ sizeof(sc->sc_rawtype), req));
+}
+
static int
asmc_key_write(device_t dev, const char *key, uint8_t *buf, uint8_t len)
{
diff --git a/sys/dev/asmc/asmcvar.h b/sys/dev/asmc/asmcvar.h
--- a/sys/dev/asmc/asmcvar.h
+++ b/sys/dev/asmc/asmcvar.h
@@ -28,6 +28,7 @@
*/
#define ASMC_MAXFANS 6
+#define ASMC_MAXVAL 32 /* Maximum SMC value size */
struct asmc_softc {
device_t sc_dev;
@@ -51,6 +52,12 @@
struct taskqueue *sc_sms_tq;
struct task sc_sms_task;
uint8_t sc_sms_intr_works;
+ /* Raw key access */
+ struct sysctl_oid *sc_raw_tree;
+ char sc_rawkey[5]; /* 4-char key + NUL */
+ uint8_t sc_rawval[ASMC_MAXVAL];
+ uint8_t sc_rawlen;
+ char sc_rawtype[5]; /* 4-char type + NUL */
};
/*

File Metadata

Mime Type
text/plain
Expires
Tue, Jan 13, 7:18 AM (6 h, 33 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27625466
Default Alt Text
D54441.id169373.diff (9 KB)

Event Timeline