There is an error in function con_set_unimap (file: linux-3.0/drivers/tty/vt/consolemap.c) During the copying of the map variable l=<current unicode value> does not increment properly. > for (i = 0, l = 0; i < 32; i++) > if ((p1 = p->uni_pgdir[i])) > ... else (if p1 == NULL) its value will be left unchanged instead of += ... Steps to reproduce: 1. fbdev driver should be used 2. Switch to virtual console 1 (Alt+F1) 3. Compile and run test1.c 4. Switch to virtual console 2 (Alt+F2) 5. Run test1.c 6. Compile and run test2.c You will get something like Current Unicode-to-font map 0x123 U+0001 // Should be U+0041 0x134 U+0042 ----- test1.c ----- #define _GNU_SOURCE #include <err.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <linux/kd.h> int main(int argc, char *argv[]) { struct unipair up = {0x0041, 0x0123}; struct unimapdesc ud = {1, &up}; int fd; fd = open("/dev/tty0", O_RDWR); if (fd < 0) err(1, "open"); if (ioctl(fd, PIO_UNIMAPCLR, &ud) < 0) err(1, "ioctl(PIO_UNIMAPCLR)"); if (ioctl(fd, PIO_UNIMAP, &ud) < 0) err(1, "ioctl(PIO_UNIMAP)"); int i, ct; ud.entry_ct = 0; ud.entries = 0; if (ioctl(fd, GIO_UNIMAP, &ud) < 0 && errno != ENOMEM) err(1, "ioctl(GIO_UNIMAP)"); ct = ud.entry_ct; ud.entries = (struct unipair *) malloc(ct * sizeof(struct unipair)); if (ud.entries == NULL) { return -1; } if (ioctl(fd, GIO_UNIMAP, &ud) < 0) err(1, "ioctl(GIO_UNIMAP)"); printf("Current Unicode-to-font map\n"); for (i = 0; i < ud.entry_ct; i++) printf("0x%02x\tU+%04x\n", ud.entries[i].fontpos, ud.entries[i].unicode); close(fd); return EXIT_SUCCESS; } ---------- ----- test2.c ----- #define _GNU_SOURCE #include <err.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <linux/kd.h> int main(int argc, char *argv[]) { struct unipair up = {0x0042, 0x0134}; struct unimapdesc ud = {1, &up}; int fd; fd = open("/dev/tty0", O_RDWR); if (fd < 0) err(1, "open"); if (ioctl(fd, PIO_UNIMAP, &ud) < 0) err(1, "ioctl(PIO_UNIMAP)"); int i, ct; ud.entry_ct = 0; ud.entries = 0; if (ioctl(fd, GIO_UNIMAP, &ud) < 0 && errno != ENOMEM) err(1, "ioctl(GIO_UNIMAP)"); ct = ud.entry_ct; ud.entries = (struct unipair *) malloc(ct * sizeof(struct unipair)); if (ud.entries == NULL) { return -1; } if (ioctl(fd, GIO_UNIMAP, &ud) < 0) err(1, "ioctl(GIO_UNIMAP)"); printf("Current Unicode-to-font map\n"); for (i = 0; i < ud.entry_ct; i++) printf("0x%02x\tU+%04x\n", ud.entries[i].fontpos, ud.entries[i].unicode); close(fd); return EXIT_SUCCESS; } ----------
A patch referencing this bug report has been merged in Linux v3.4-rc1: commit 4a4c61b7ce26bfc9d49ea4bd121d52114bad9f99 Author: Liz Clark <liz.clark@hp.com> Date: Thu Mar 15 10:33:29 2012 -0700 TTY: Wrong unicode value copied in con_set_unimap()