On Wed, Jan 27, 2016 at 05:20:59AM +0200, Sviatoslav Chagaev wrote:
> On Sun, 10 Jan 2016 21:28:31 +0100 Joerg Jung wrote:
> > On Sun, Jan 10, 2016 at 04:59:22AM +0200, Sviatoslav Chagaev wrote: 
> > > So below is a driver for TI LP8550.
> ...
> > > If there's any chance for it to be commited, please tell me what I need to
> > > fix/improve to get it commited (so I don't have to reapply it every time I
> > > upgrade).
> > 
> > IMHO, instead of adding another driver to the mix, I would prefer this 
> > to be handled through the associated asmc(4) keys instead of accessing
> > the chip directly.  The SMC is supposed to be the central point for such
> > manipulations.  Unfortunately, the keys are not documented and need some
> > non-trivial effort to be figured out.
> > 
> > If this is not possible through asmc(4) and if your new driver improves
> > the situation then I'm fine with importing it, but for now it is just
> > worse.
> > 
> 
> Using knowledge acquired from [1]

[1] contains some "wrong" (obsolete?) information, e.g. the Errors list.

> and [2] made a diff, posted below for
> reference, which adds:
>  * ioctl interface to asmc(4) to allow reading/writing of ``keys'' from
>    userspace;
>  * companion smcprobe(1) which reads/writes ``keys'' using the ioctl;

Wow..., much effort for simple key dumping.  Please, find below an
(older/may not apply) diff which just dumps the keys directly from
kernel into dmesg.

Are you aware that keys can be all kind of types, e.g. structs?  Have
you seen the ASMC_INFO (0x13) command which might be used to determine
the type?  The key flags (read/write/atomic...) are mostly documented
somewhere.

>  * smcdumpkeys(1): scans an SMC textual firmware file and dumps the ``key''
>    table that it contains.

Are you aware of the ASMC_INDEX (0x12) command, which can easily be used
to just iterate ALL keys based on index?

> Downloaded SMC FW [3], unpacked it using Google Drive and used smcdumpkeys(1) 
> +
> smcprobe(1) to create the table of keys and their current values before 
> suspend
> [4] and after wake up [5]. Diffed them [6], 

The diff approach is interesting... :) From your diff output I would try
to play with IPBF, MSXk, SAPN, and DM0T.

> filtering out keys which change over
> time as they are probably sensors (some might have gotten through).

If they start with:

'A'... usually ambient light sensor related,
'F'... fan sensors,
'T'... temperature sensors,
'P'... power related,
'V'... voltage sensors.

> Tried modifying all keys whose names start with 'B': no effect.

'B'... is likely not "backlight" but "battery".

> Tried modifying keys which are different after wake up: no effect.

Please find a more exhaustive/descriptive list of keys here:
http://web.archive.org/web/20151103144947/http://www.parhelia.ch/blog/statics/k3_keys.html

Have you seen this: https://github.com/gcsgithub/smc_util it contains
more details for the various structs.

You may also want to have a look into the existing FreeBSD and Linux
drivers.

> [1] 
> https://reverse.put.as/wp-content/uploads/2015/12/D1_02_Alex_Ninjas_and_Harry_Potter.pdf
> [2] 
> https://dev.inversepath.com/download/public/embedded_systems_exploitation.pdf
> [3] https://support.apple.com/kb/DL1748?locale=en_US
> [4] https://gist.github.com/S010/26145f4446fcc0b8a0d6#file-before_suspend-txt
> [5] https://gist.github.com/S010/26145f4446fcc0b8a0d6#file-after_wakeup-txt
> [6] 
> https://gist.github.com/S010/26145f4446fcc0b8a0d6#file-suspend_wakeup_key-diff


Index: asmc.c
===================================================================
RCS file: /cvs/src/sys/dev/isa/asmc.c,v
retrieving revision 1.17
diff -u -p -r1.17 asmc.c
--- asmc.c      12 Dec 2015 12:34:05 -0000      1.17
+++ asmc.c      12 Dec 2015 13:30:12 -0000
@@ -32,6 +32,8 @@
 #include <dev/isa/isavar.h>
 #include <dev/wscons/wsconsio.h>
 
+#define ASMC_DEBUG     1
+
 #define ASMC_BASE      0x300   /* SMC base address */
 #define ASMC_IOSIZE    32      /* I/O region size 0x300-0x31f */
 
@@ -42,6 +44,7 @@
 
 #define ASMC_READ      0x10    /* SMC read command */
 #define ASMC_WRITE     0x11    /* SMC write command */
+#define ASMC_INDEX     0x12    /* SMC index command */
 #define ASMC_INFO      0x13    /* SMC info/type command */
 
 #define ASMC_RETRY     10
@@ -85,6 +88,9 @@ struct asmc_softc {
 };
 
 int    asmc_try(struct asmc_softc *, int, const char *, uint8_t *, uint8_t);
+#ifdef ASMC_DEBUG
+void   asmc_dump(struct asmc_softc *, uint32_t);
+#endif
 
 void   asmc_init(void *);
 void   asmc_refresh(void *);
@@ -292,7 +298,9 @@ asmc_attach(struct device *parent, struc
        }
        printf(", %u key%s\n", ntohl(*(uint32_t *)buf),
            (ntohl(*(uint32_t *)buf) == 1) ? "" : "s");
-
+#ifdef ASMC_DEBUG
+       asmc_dump(sc, ntohl(*(uint32_t *)buf));
+#endif
        /* keyboard backlight led is optional */
        sc->sc_kbdled = buf[0] = 127, buf[1] = 0;
        if ((r = asmc_try(sc, ASMC_WRITE, "LKSB", buf, 2))) {
@@ -479,25 +487,25 @@ asmc_command(struct asmc_softc *sc, int 
        if (len > ASMC_MAXLEN)
                return 1;
        if (asmc_write(sc, ASMC_COMMAND, cmd))
-               return 1;
+               return 2;
        for (i = 0; i < 4; i++)
                if (asmc_write(sc, ASMC_DATA, key[i]))
-                       return 1;
+                       return 3;
        if (asmc_write(sc, ASMC_DATA, len))
-               return 1;
-       if (cmd == ASMC_READ || cmd == ASMC_INFO) {
+               return 4;
+       if (cmd == ASMC_READ || cmd == ASMC_INDEX || cmd == ASMC_INFO) {
                for (i = 0; i < len; i++)
                        if (asmc_read(sc, ASMC_DATA, &buf[i]))
-                               return 1;
+                               return 5;
                for (i = 0; i < ASMC_MAXLEN; i++) /* sanity flush */
                        if (asmc_read(sc, ASMC_DATA, &n))
                                break;
        } else if (cmd == ASMC_WRITE) {
                for (i = 0; i < len; i++)
                        if (asmc_write(sc, ASMC_DATA, buf[i]))
-                               return 1;
+                               return 6;
        } else
-               return 1;
+               return 7;
        return 0;
 }
 
@@ -750,3 +758,40 @@ asmc_update(void *arg)
        if (sc->sc_init)
                task_add(sc->sc_taskq, &sc->sc_task_refresh);
 }
+
+#ifdef ASMC_DEBUG
+void
+asmc_dump(struct asmc_softc *sc, uint32_t len)
+{
+       uint8_t buf[4], key[4];
+       uint32_t i;
+       int r, e;
+
+       for (i = 0; i < len; i++, e = 0) {
+               *(uint32_t *)buf = htonl(i);
+               printf("%s: dump key[%u]", sc->sc_dev.dv_xname, i);
+retry:
+               if ((r = asmc_try(sc, ASMC_INDEX, buf, key, 4))) {
+                       printf(" failed (0x%x)\n", r);
+                       continue;
+               }
+               if (!key[0] || !strncmp(key, "Pz0F", 4)) {
+                       if (++e < ASMC_RETRY) {
+                               delay(2 << 16);
+                               goto retry;
+                       }
+                       printf(" *");
+               }
+               printf(" '%c%c%c%c'", key[0], key[1], key[2], key[3]);
+               if (key[0] == 'T' || key[0] == 't') {
+                       delay(2 << 16);
+                       if (!(r = asmc_try(sc, ASMC_READ, key, buf, 2)))
+                               printf(" t: %hd",
+                                   (((int16_t)ntohs(*(uint16_t *)buf)) >> 8));
+                       printf(" (0x%x)", r);
+               }
+               printf("\n");
+               delay(2 << 16);
+       }
+}
+#endif

Reply via email to