tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Patching wscons_keydesc at runtime
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.
Is the patch below fine to commit, or is there a smarter way to sort this out?
I am not sure why hpc(adm|mips|sh) ports need to patch this const data and if
it can be done differently.
Another point: In order to have french keymap, I used to do wsconsctl -w
encoding=fr, and I must now do wsconsctl -w encoding=fr.machdep. I wonder ig
it is on purpose or if it is a bug (that is: should the KB_MACHDEP flag be
filtered somewhere?)
--- sys/dev/hpc/hpckbd.c 27 Oct 2012 17:18:17 -0000 1.30
+++ sys/dev/hpc/hpckbd.c 9 Jun 2017 15:34:42 -0000
@@ -34,8 +34,9 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
+#include <sys/malloc.h>
#include <sys/tty.h>
#include <sys/bus.h>
@@ -263,24 +264,32 @@
hpckbd_keymap_setup(struct hpckbd_core *hc,
const keysym_t *map, int mapsize)
{
int i;
- struct wscons_keydesc *desc;
+ const struct wscons_keydesc *desc;
+ static struct wscons_keydesc *ndesc = NULL;
- /* 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.
+ * fix keydesc table. Since it is const data, we must
+ * copy it once before changingg it.
*/
- desc = (struct wscons_keydesc *)__UNCONST(hpckbd_keymapdata.keydesc);
+
+ if (ndesc == NULL) {
+ size_t sz;
+
+ for (sz = 0; hpckbd_keymapdata.keydesc[sz].name != 0; sz++);
+
+ ndesc = malloc(sz * sizeof(*ndesc), M_DEVBUF, M_WAITOK);
+ memcpy(ndesc, hpckbd_keymapdata.keydesc, sz * sizeof(*ndesc));
+
+ hpckbd_keymapdata.keydesc = ndesc;
+ }
+
+ desc = 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;
+ ndesc[i].map = map;
+ ndesc[i].map_size = mapsize;
}
}
return;
--
Emmanuel Dreyfus
http://hcpnet.free.fr/pubz
manu%netbsd.org@localhost
Home |
Main Index |
Thread Index |
Old Index