linux/drivers/tty/vt/consolemap.c
<<
>>
Prefs
   1/*
   2 * consolemap.c
   3 *
   4 * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
   5 * to font positions.
   6 *
   7 * aeb, 950210
   8 *
   9 * Support for multiple unimaps by Jakub Jelinek <jj@ultra.linux.cz>, July 1998
  10 *
  11 * Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
  12 */
  13
  14#include <linux/module.h>
  15#include <linux/kd.h>
  16#include <linux/errno.h>
  17#include <linux/mm.h>
  18#include <linux/slab.h>
  19#include <linux/init.h>
  20#include <linux/tty.h>
  21#include <asm/uaccess.h>
  22#include <linux/console.h>
  23#include <linux/consolemap.h>
  24#include <linux/vt_kern.h>
  25
  26static unsigned short translations[][256] = {
  27  /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
  28  {
  29    0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
  30    0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
  31    0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
  32    0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
  33    0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  34    0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
  35    0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
  36    0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
  37    0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
  38    0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
  39    0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
  40    0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
  41    0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
  42    0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
  43    0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
  44    0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
  45    0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
  46    0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
  47    0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
  48    0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
  49    0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
  50    0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
  51    0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
  52    0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
  53    0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
  54    0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
  55    0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
  56    0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
  57    0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
  58    0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
  59    0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
  60    0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
  61  }, 
  62  /* VT100 graphics mapped to Unicode */
  63  {
  64    0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
  65    0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
  66    0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
  67    0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
  68    0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  69    0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
  70    0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
  71    0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
  72    0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
  73    0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
  74    0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
  75    0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
  76    0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
  77    0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
  78    0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
  79    0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
  80    0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
  81    0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
  82    0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
  83    0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
  84    0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
  85    0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
  86    0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
  87    0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
  88    0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
  89    0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
  90    0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
  91    0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
  92    0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
  93    0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
  94    0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
  95    0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
  96  },
  97  /* IBM Codepage 437 mapped to Unicode */
  98  {
  99    0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, 
 100    0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
 101    0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
 102    0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
 103    0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
 104    0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
 105    0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
 106    0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
 107    0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
 108    0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
 109    0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
 110    0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
 111    0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
 112    0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
 113    0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
 114    0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
 115    0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
 116    0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
 117    0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
 118    0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
 119    0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
 120    0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
 121    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
 122    0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
 123    0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
 124    0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
 125    0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
 126    0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
 127    0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
 128    0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
 129    0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
 130    0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
 131  }, 
 132  /* User mapping -- default to codes for direct font mapping */
 133  {
 134    0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
 135    0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
 136    0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
 137    0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
 138    0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
 139    0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
 140    0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
 141    0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
 142    0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
 143    0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
 144    0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
 145    0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
 146    0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
 147    0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
 148    0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
 149    0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
 150    0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
 151    0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
 152    0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
 153    0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
 154    0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
 155    0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
 156    0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
 157    0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
 158    0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
 159    0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
 160    0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
 161    0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
 162    0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
 163    0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
 164    0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
 165    0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
 166  }
 167};
 168
 169/* The standard kernel character-to-font mappings are not invertible
 170   -- this is just a best effort. */
 171
 172#define MAX_GLYPH 512           /* Max possible glyph value */
 173
 174static int inv_translate[MAX_NR_CONSOLES];
 175
 176struct uni_pagedir {
 177        u16             **uni_pgdir[32];
 178        unsigned long   refcount;
 179        unsigned long   sum;
 180        unsigned char   *inverse_translations[4];
 181        u16             *inverse_trans_unicode;
 182};
 183
 184static struct uni_pagedir *dflt;
 185
 186static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
 187{
 188        int j, glyph;
 189        unsigned short *t = translations[i];
 190        unsigned char *q;
 191        
 192        if (!p) return;
 193        q = p->inverse_translations[i];
 194
 195        if (!q) {
 196                q = p->inverse_translations[i] = kmalloc(MAX_GLYPH, GFP_KERNEL);
 197                if (!q) return;
 198        }
 199        memset(q, 0, MAX_GLYPH);
 200
 201        for (j = 0; j < E_TABSZ; j++) {
 202                glyph = conv_uni_to_pc(conp, t[j]);
 203                if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
 204                        /* prefer '-' above SHY etc. */
 205                        q[glyph] = j;
 206                }
 207        }
 208}
 209
 210static void set_inverse_trans_unicode(struct vc_data *conp,
 211                                      struct uni_pagedir *p)
 212{
 213        int i, j, k, glyph;
 214        u16 **p1, *p2;
 215        u16 *q;
 216
 217        if (!p) return;
 218        q = p->inverse_trans_unicode;
 219        if (!q) {
 220                q = p->inverse_trans_unicode =
 221                        kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
 222                if (!q)
 223                        return;
 224        }
 225        memset(q, 0, MAX_GLYPH * sizeof(u16));
 226
 227        for (i = 0; i < 32; i++) {
 228                p1 = p->uni_pgdir[i];
 229                if (!p1)
 230                        continue;
 231                for (j = 0; j < 32; j++) {
 232                        p2 = p1[j];
 233                        if (!p2)
 234                                continue;
 235                        for (k = 0; k < 64; k++) {
 236                                glyph = p2[k];
 237                                if (glyph >= 0 && glyph < MAX_GLYPH
 238                                               && q[glyph] < 32)
 239                                        q[glyph] = (i << 11) + (j << 6) + k;
 240                        }
 241                }
 242        }
 243}
 244
 245unsigned short *set_translate(int m, struct vc_data *vc)
 246{
 247        inv_translate[vc->vc_num] = m;
 248        return translations[m];
 249}
 250
 251/*
 252 * Inverse translation is impossible for several reasons:
 253 * 1. The font<->character maps are not 1-1.
 254 * 2. The text may have been written while a different translation map
 255 *    was active.
 256 * Still, it is now possible to a certain extent to cut and paste non-ASCII.
 257 */
 258u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
 259{
 260        struct uni_pagedir *p;
 261        int m;
 262        if (glyph < 0 || glyph >= MAX_GLYPH)
 263                return 0;
 264        else {
 265                p = *conp->vc_uni_pagedir_loc;
 266                if (!p)
 267                        return glyph;
 268                else if (use_unicode) {
 269                        if (!p->inverse_trans_unicode)
 270                                return glyph;
 271                        else
 272                                return p->inverse_trans_unicode[glyph];
 273                        } else {
 274                        m = inv_translate[conp->vc_num];
 275                        if (!p->inverse_translations[m])
 276                                return glyph;
 277                        else
 278                                return p->inverse_translations[m][glyph];
 279                        }
 280        }
 281}
 282EXPORT_SYMBOL_GPL(inverse_translate);
 283
 284static void update_user_maps(void)
 285{
 286        int i;
 287        struct uni_pagedir *p, *q = NULL;
 288        
 289        for (i = 0; i < MAX_NR_CONSOLES; i++) {
 290                if (!vc_cons_allocated(i))
 291                        continue;
 292                p = *vc_cons[i].d->vc_uni_pagedir_loc;
 293                if (p && p != q) {
 294                        set_inverse_transl(vc_cons[i].d, p, USER_MAP);
 295                        set_inverse_trans_unicode(vc_cons[i].d, p);
 296                        q = p;
 297                }
 298        }
 299}
 300
 301/*
 302 * Load customizable translation table
 303 * arg points to a 256 byte translation table.
 304 *
 305 * The "old" variants are for translation directly to font (using the
 306 * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
 307 * Unicodes explicitly.
 308 */
 309int con_set_trans_old(unsigned char __user * arg)
 310{
 311        int i;
 312        unsigned short *p = translations[USER_MAP];
 313
 314        if (!access_ok(VERIFY_READ, arg, E_TABSZ))
 315                return -EFAULT;
 316
 317        console_lock();
 318        for (i=0; i<E_TABSZ ; i++) {
 319                unsigned char uc;
 320                __get_user(uc, arg+i);
 321                p[i] = UNI_DIRECT_BASE | uc;
 322        }
 323
 324        update_user_maps();
 325        console_unlock();
 326        return 0;
 327}
 328
 329int con_get_trans_old(unsigned char __user * arg)
 330{
 331        int i, ch;
 332        unsigned short *p = translations[USER_MAP];
 333
 334        if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
 335                return -EFAULT;
 336
 337        console_lock();
 338        for (i=0; i<E_TABSZ ; i++)
 339        {
 340                ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
 341                __put_user((ch & ~0xff) ? 0 : ch, arg+i);
 342        }
 343        console_unlock();
 344        return 0;
 345}
 346
 347int con_set_trans_new(ushort __user * arg)
 348{
 349        int i;
 350        unsigned short *p = translations[USER_MAP];
 351
 352        if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
 353                return -EFAULT;
 354
 355        console_lock();
 356        for (i=0; i<E_TABSZ ; i++) {
 357                unsigned short us;
 358                __get_user(us, arg+i);
 359                p[i] = us;
 360        }
 361
 362        update_user_maps();
 363        console_unlock();
 364        return 0;
 365}
 366
 367int con_get_trans_new(ushort __user * arg)
 368{
 369        int i;
 370        unsigned short *p = translations[USER_MAP];
 371
 372        if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
 373                return -EFAULT;
 374
 375        console_lock();
 376        for (i=0; i<E_TABSZ ; i++)
 377          __put_user(p[i], arg+i);
 378        console_unlock();
 379        
 380        return 0;
 381}
 382
 383/*
 384 * Unicode -> current font conversion 
 385 *
 386 * A font has at most 512 chars, usually 256.
 387 * But one font position may represent several Unicode chars.
 388 * A hashtable is somewhat of a pain to deal with, so use a
 389 * "paged table" instead.  Simulation has shown the memory cost of
 390 * this 3-level paged table scheme to be comparable to a hash table.
 391 */
 392
 393extern u8 dfont_unicount[];     /* Defined in console_defmap.c */
 394extern u16 dfont_unitable[];
 395
 396static void con_release_unimap(struct uni_pagedir *p)
 397{
 398        u16 **p1;
 399        int i, j;
 400
 401        if (p == dflt) dflt = NULL;  
 402        for (i = 0; i < 32; i++) {
 403                p1 = p->uni_pgdir[i];
 404                if (p1 != NULL) {
 405                        for (j = 0; j < 32; j++)
 406                                kfree(p1[j]);
 407                        kfree(p1);
 408                }
 409                p->uni_pgdir[i] = NULL;
 410        }
 411        for (i = 0; i < 4; i++) {
 412                kfree(p->inverse_translations[i]);
 413                p->inverse_translations[i] = NULL;
 414        }
 415        kfree(p->inverse_trans_unicode);
 416        p->inverse_trans_unicode = NULL;
 417}
 418
 419/* Caller must hold the console lock */
 420void con_free_unimap(struct vc_data *vc)
 421{
 422        struct uni_pagedir *p;
 423
 424        p = *vc->vc_uni_pagedir_loc;
 425        if (!p)
 426                return;
 427        *vc->vc_uni_pagedir_loc = NULL;
 428        if (--p->refcount)
 429                return;
 430        con_release_unimap(p);
 431        kfree(p);
 432}
 433  
 434static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
 435{
 436        int i, j, k;
 437        struct uni_pagedir *q;
 438        
 439        for (i = 0; i < MAX_NR_CONSOLES; i++) {
 440                if (!vc_cons_allocated(i))
 441                        continue;
 442                q = *vc_cons[i].d->vc_uni_pagedir_loc;
 443                if (!q || q == p || q->sum != p->sum)
 444                        continue;
 445                for (j = 0; j < 32; j++) {
 446                        u16 **p1, **q1;
 447                        p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
 448                        if (!p1 && !q1)
 449                                continue;
 450                        if (!p1 || !q1)
 451                                break;
 452                        for (k = 0; k < 32; k++) {
 453                                if (!p1[k] && !q1[k])
 454                                        continue;
 455                                if (!p1[k] || !q1[k])
 456                                        break;
 457                                if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
 458                                        break;
 459                        }
 460                        if (k < 32)
 461                                break;
 462                }
 463                if (j == 32) {
 464                        q->refcount++;
 465                        *conp->vc_uni_pagedir_loc = q;
 466                        con_release_unimap(p);
 467                        kfree(p);
 468                        return 1;
 469                }
 470        }
 471        return 0;
 472}
 473
 474static int
 475con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
 476{
 477        int i, n;
 478        u16 **p1, *p2;
 479
 480        p1 = p->uni_pgdir[n = unicode >> 11];
 481        if (!p1) {
 482                p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
 483                if (!p1) return -ENOMEM;
 484                for (i = 0; i < 32; i++)
 485                        p1[i] = NULL;
 486        }
 487
 488        p2 = p1[n = (unicode >> 6) & 0x1f];
 489        if (!p2) {
 490                p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
 491                if (!p2) return -ENOMEM;
 492                memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
 493        }
 494
 495        p2[unicode & 0x3f] = fontpos;
 496        
 497        p->sum += (fontpos << 20) + unicode;
 498
 499        return 0;
 500}
 501
 502/* Caller must hold the lock */
 503static int con_do_clear_unimap(struct vc_data *vc)
 504{
 505        struct uni_pagedir *p, *q;
 506
 507        p = *vc->vc_uni_pagedir_loc;
 508        if (!p || --p->refcount) {
 509                q = kzalloc(sizeof(*p), GFP_KERNEL);
 510                if (!q) {
 511                        if (p)
 512                                p->refcount++;
 513                        return -ENOMEM;
 514                }
 515                q->refcount=1;
 516                *vc->vc_uni_pagedir_loc = q;
 517        } else {
 518                if (p == dflt) dflt = NULL;
 519                p->refcount++;
 520                p->sum = 0;
 521                con_release_unimap(p);
 522        }
 523        return 0;
 524}
 525
 526int con_clear_unimap(struct vc_data *vc)
 527{
 528        int ret;
 529        console_lock();
 530        ret = con_do_clear_unimap(vc);
 531        console_unlock();
 532        return ret;
 533}
 534        
 535int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
 536{
 537        int err = 0, err1, i;
 538        struct uni_pagedir *p, *q;
 539
 540        if (!ct)
 541                return 0;
 542
 543        console_lock();
 544
 545        /* Save original vc_unipagdir_loc in case we allocate a new one */
 546        p = *vc->vc_uni_pagedir_loc;
 547
 548        if (!p) {
 549                err = -EINVAL;
 550
 551                goto out_unlock;
 552        }
 553        
 554        if (p->refcount > 1) {
 555                int j, k;
 556                u16 **p1, *p2, l;
 557                
 558                err1 = con_do_clear_unimap(vc);
 559                if (err1) {
 560                        console_unlock();
 561                        return err1;
 562                }
 563                
 564                /*
 565                 * Since refcount was > 1, con_clear_unimap() allocated a
 566                 * a new uni_pagedir for this vc.  Re: p != q
 567                 */
 568                q = *vc->vc_uni_pagedir_loc;
 569
 570                /*
 571                 * uni_pgdir is a 32*32*64 table with rows allocated
 572                 * when its first entry is added.  The unicode value must
 573                 * still be incremented for empty rows.  We are copying
 574                 * entries from "p" (old) to "q" (new).
 575                 */
 576                l = 0;          /* unicode value */
 577                for (i = 0; i < 32; i++) {
 578                p1 = p->uni_pgdir[i];
 579                if (p1)
 580                        for (j = 0; j < 32; j++) {
 581                        p2 = p1[j];
 582                        if (p2) {
 583                                for (k = 0; k < 64; k++, l++)
 584                                if (p2[k] != 0xffff) {
 585                                        /*
 586                                         * Found one, copy entry for unicode
 587                                         * l with fontpos value p2[k].
 588                                         */
 589                                        err1 = con_insert_unipair(q, l, p2[k]);
 590                                        if (err1) {
 591                                                p->refcount++;
 592                                                *vc->vc_uni_pagedir_loc = p;
 593                                                con_release_unimap(q);
 594                                                kfree(q);
 595                                                console_unlock();
 596                                                return err1; 
 597                                        }
 598                                }
 599                        } else {
 600                                /* Account for row of 64 empty entries */
 601                                l += 64;
 602                        }
 603                }
 604                else
 605                        /* Account for empty table */
 606                        l += 32 * 64;
 607                }
 608
 609                /*
 610                 * Finished copying font table, set vc_uni_pagedir to new table
 611                 */
 612                p = q;
 613        } else if (p == dflt) {
 614                dflt = NULL;
 615        }
 616
 617        /*
 618         * Insert user specified unicode pairs into new table.
 619         */
 620        while (ct--) {
 621                unsigned short unicode, fontpos;
 622                __get_user(unicode, &list->unicode);
 623                __get_user(fontpos, &list->fontpos);
 624                if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
 625                        err = err1;
 626                list++;
 627        }
 628        
 629        /*
 630         * Merge with fontmaps of any other virtual consoles.
 631         */
 632        if (con_unify_unimap(vc, p)) {
 633                console_unlock();
 634                return err;
 635        }
 636
 637        for (i = 0; i <= 3; i++)
 638                set_inverse_transl(vc, p, i); /* Update inverse translations */
 639        set_inverse_trans_unicode(vc, p);
 640
 641out_unlock:
 642        console_unlock();
 643        return err;
 644}
 645
 646/**
 647 *      con_set_default_unimap  -       set default unicode map
 648 *      @vc: the console we are updating
 649 *
 650 *      Loads the unimap for the hardware font, as defined in uni_hash.tbl.
 651 *      The representation used was the most compact I could come up
 652 *      with.  This routine is executed at video setup, and when the
 653 *      PIO_FONTRESET ioctl is called. 
 654 *
 655 *      The caller must hold the console lock
 656 */
 657int con_set_default_unimap(struct vc_data *vc)
 658{
 659        int i, j, err = 0, err1;
 660        u16 *q;
 661        struct uni_pagedir *p;
 662
 663        if (dflt) {
 664                p = *vc->vc_uni_pagedir_loc;
 665                if (p == dflt)
 666                        return 0;
 667
 668                dflt->refcount++;
 669                *vc->vc_uni_pagedir_loc = dflt;
 670                if (p && !--p->refcount) {
 671                        con_release_unimap(p);
 672                        kfree(p);
 673                }
 674                return 0;
 675        }
 676        
 677        /* The default font is always 256 characters */
 678
 679        err = con_do_clear_unimap(vc);
 680        if (err)
 681                return err;
 682    
 683        p = *vc->vc_uni_pagedir_loc;
 684        q = dfont_unitable;
 685        
 686        for (i = 0; i < 256; i++)
 687                for (j = dfont_unicount[i]; j; j--) {
 688                        err1 = con_insert_unipair(p, *(q++), i);
 689                        if (err1)
 690                                err = err1;
 691                }
 692                        
 693        if (con_unify_unimap(vc, p)) {
 694                dflt = *vc->vc_uni_pagedir_loc;
 695                return err;
 696        }
 697
 698        for (i = 0; i <= 3; i++)
 699                set_inverse_transl(vc, p, i);   /* Update all inverse translations */
 700        set_inverse_trans_unicode(vc, p);
 701        dflt = p;
 702        return err;
 703}
 704EXPORT_SYMBOL(con_set_default_unimap);
 705
 706/**
 707 *      con_copy_unimap         -       copy unimap between two vts
 708 *      @dst_vc: target
 709 *      @src_vt: source
 710 *
 711 *      The caller must hold the console lock when invoking this method
 712 */
 713int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
 714{
 715        struct uni_pagedir *q;
 716
 717        if (!*src_vc->vc_uni_pagedir_loc)
 718                return -EINVAL;
 719        if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
 720                return 0;
 721        con_free_unimap(dst_vc);
 722        q = *src_vc->vc_uni_pagedir_loc;
 723        q->refcount++;
 724        *dst_vc->vc_uni_pagedir_loc = q;
 725        return 0;
 726}
 727EXPORT_SYMBOL(con_copy_unimap);
 728
 729/**
 730 *      con_get_unimap          -       get the unicode map
 731 *      @vc: the console to read from
 732 *
 733 *      Read the console unicode data for this console. Called from the ioctl
 734 *      handlers.
 735 */
 736int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
 737{
 738        int i, j, k, ect;
 739        u16 **p1, *p2;
 740        struct uni_pagedir *p;
 741
 742        console_lock();
 743
 744        ect = 0;
 745        if (*vc->vc_uni_pagedir_loc) {
 746                p = *vc->vc_uni_pagedir_loc;
 747                for (i = 0; i < 32; i++) {
 748                p1 = p->uni_pgdir[i];
 749                if (p1)
 750                        for (j = 0; j < 32; j++) {
 751                        p2 = *(p1++);
 752                        if (p2)
 753                                for (k = 0; k < 64; k++) {
 754                                        if (*p2 < MAX_GLYPH && ect++ < ct) {
 755                                                __put_user((u_short)((i<<11)+(j<<6)+k),
 756                                                           &list->unicode);
 757                                                __put_user((u_short) *p2, 
 758                                                           &list->fontpos);
 759                                                list++;
 760                                        }
 761                                        p2++;
 762                                }
 763                        }
 764                }
 765        }
 766        __put_user(ect, uct);
 767        console_unlock();
 768        return ((ect <= ct) ? 0 : -ENOMEM);
 769}
 770
 771/*
 772 * Always use USER_MAP. These functions are used by the keyboard,
 773 * which shouldn't be affected by G0/G1 switching, etc.
 774 * If the user map still contains default values, i.e. the
 775 * direct-to-font mapping, then assume user is using Latin1.
 776 *
 777 * FIXME: at some point we need to decide if we want to lock the table
 778 * update element itself via the keyboard_event_lock for consistency with the
 779 * keyboard driver as well as the consoles
 780 */
 781/* may be called during an interrupt */
 782u32 conv_8bit_to_uni(unsigned char c)
 783{
 784        unsigned short uni = translations[USER_MAP][c];
 785        return uni == (0xf000 | c) ? c : uni;
 786}
 787
 788int conv_uni_to_8bit(u32 uni)
 789{
 790        int c;
 791        for (c = 0; c < 0x100; c++)
 792                if (translations[USER_MAP][c] == uni ||
 793                   (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
 794                        return c;
 795        return -1;
 796}
 797
 798int
 799conv_uni_to_pc(struct vc_data *conp, long ucs) 
 800{
 801        int h;
 802        u16 **p1, *p2;
 803        struct uni_pagedir *p;
 804  
 805        /* Only 16-bit codes supported at this time */
 806        if (ucs > 0xffff)
 807                return -4;              /* Not found */
 808        else if (ucs < 0x20)
 809                return -1;              /* Not a printable character */
 810        else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
 811                return -2;                      /* Zero-width space */
 812        /*
 813         * UNI_DIRECT_BASE indicates the start of the region in the User Zone
 814         * which always has a 1:1 mapping to the currently loaded font.  The
 815         * UNI_DIRECT_MASK indicates the bit span of the region.
 816         */
 817        else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
 818                return ucs & UNI_DIRECT_MASK;
 819  
 820        if (!*conp->vc_uni_pagedir_loc)
 821                return -3;
 822
 823        p = *conp->vc_uni_pagedir_loc;
 824        if ((p1 = p->uni_pgdir[ucs >> 11]) &&
 825            (p2 = p1[(ucs >> 6) & 0x1f]) &&
 826            (h = p2[ucs & 0x3f]) < MAX_GLYPH)
 827                return h;
 828
 829        return -4;              /* not found */
 830}
 831
 832/*
 833 * This is called at sys_setup time, after memory and the console are
 834 * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
 835 * from this function, hence the call from sys_setup.
 836 */
 837void __init 
 838console_map_init(void)
 839{
 840        int i;
 841        
 842        for (i = 0; i < MAX_NR_CONSOLES; i++)
 843                if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
 844                        con_set_default_unimap(vc_cons[i].d);
 845}
 846
 847