tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Wskbd constness (Was: Patching wscons_keydesc at runtime)



On Sat, Jun 10, 2017 at 05:18:16 +0200, Emmanuel Dreyfus wrote:

> I just upgraded an HP Jornada 720 from NetBSD 2.0 to NetBSD 7.1, and
> discovered the wscons keymaps were broken in the meantime: it is impossible to
> change the keymap using wsconsctl encoding or wsconsctl map. Both commands
> succeed but have no effect.
> 
> After poking a few printf in the kernel, I found this in
> src/sys/dev/hpc/hpckbd.c:
> 
>         /* fix keydesc table */
>         /* 
>          * XXX The way this is done is really wrong.  The __UNCONST()
>          * is a hint as to what is wrong.  This actually ends up modifying
>          * initialized data which is marked "const".
>          * The reason we get away with it here is apparently that text
>          * and read-only data gets mapped read/write on the platforms
>          * using this code.
>          */
>         desc = (struct wscons_keydesc *)__UNCONST(hpckbd_keymapdata.keydesc);
>         for (i = 0; desc[i].name != 0; i++) {
>                 if ((desc[i].name & KB_MACHDEP) && desc[i].map == NULL) {
>                         desc[i].map = map;
>                         desc[i].map_size = mapsize;
>                 }
>         }
> 
> I managed to restore wscons keymaps by copying hpckbd_keymapdata.keydesc into
> a malloc() buffer and changing the hpckbd_keymapdata.keydesc to the new
> location, which is mapped read/write. 
> 
> The offending code did not change since NetBSD 2.0, except the XXX comment
> added in 2015. That suggests the compiler behavior changed about initalized
> const data, which was still mapped R/W in the ancient time and is now really
> read-only, altough it accepts nilpotent writes without raising an exception.

The constness in the MI wskbd code looks wrong:

    /* KBD_NULLMAP generates a entry for machine native variant.
       the entry will be modified by machine dependent keyboard driver. */
    #define KBD_NULLMAP() ...

    const struct wscons_keydesc pckbd_keydesctab[] = {
    ...
            /* placeholders */
            KBD_NULLMAP(KB_US | KB_MACHDEP, KB_US),
    ...
    };

Which is obviously self-contradictory.


This is probably b/c induced by const in:

    struct wskbd_mapdata {
            const struct wscons_keydesc *keydesc;
            kbd_t layout;
    };



> +               for (sz = 0; hpckbd_keymapdata.keydesc[sz].name != 0; sz++);

/usr/share/misc/style requires explicit no-op "continue" here.


-uwe


Home | Main Index | Thread Index | Old Index