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/* ui is a leftover from using a hashtable, but might be used again
 503   Caller must hold the lock */
 504static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
 505{
 506        struct uni_pagedir *p, *q;
 507
 508        p = *vc->vc_uni_pagedir_loc;
 509        if (!p || --p->refcount) {
 510                q = kzalloc(sizeof(*p), GFP_KERNEL);
 511                if (!q) {
 512                        if (p)
 513                                p->refcount++;
 514                        return -ENOMEM;
 515                }
 516                q->refcount=1;
 517                *vc->vc_uni_pagedir_loc = q;
 518        } else {
 519                if (p == dflt) dflt = NULL;
 520                p->refcount++;
 521                p->sum = 0;
 522                con_release_unimap(p);
 523        }
 524        return 0;
 525}
 526
 527int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
 528{
 529        int ret;
 530        console_lock();
 531        ret = con_do_clear_unimap(vc, ui);
 532        console_unlock();
 533        return ret;
 534}
 535        
 536int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
 537{
 538        int err = 0, err1, i;
 539        struct uni_pagedir *p, *q;
 540
 541        if (!ct)
 542                return 0;
 543
 544        console_lock();
 545
 546        /* Save original vc_unipagdir_loc in case we allocate a new one */
 547        p = *vc->vc_uni_pagedir_loc;
 548
 549        if (!p) {
 550                err = -EINVAL;
 551
 552                goto out_unlock;
 553        }
 554        
 555        if (p->refcount > 1) {
 556                int j, k;
 557                u16 **p1, *p2, l;
 558                
 559                err1 = con_do_clear_unimap(vc, NULL);
 560                if (err1) {
 561                        console_unlock();
 562                        return err1;
 563                }
 564                
 565                /*
 566                 * Since refcount was > 1, con_clear_unimap() allocated a
 567                 * a new uni_pagedir for this vc.  Re: p != q
 568                 */
 569                q = *vc->vc_uni_pagedir_loc;
 570
 571                /*
 572                 * uni_pgdir is a 32*32*64 table with rows allocated
 573                 * when its first entry is added.  The unicode value must
 574                 * still be incremented for empty rows.  We are copying
 575                 * entries from "p" (old) to "q" (new).
 576                 */
 577                l = 0;          /* unicode value */
 578                for (i = 0; i < 32; i++) {
 579                p1 = p->uni_pgdir[i];
 580                if (p1)
 581                        for (j = 0; j < 32; j++) {
 582                        p2 = p1[j];
 583                        if (p2) {
 584                                for (k = 0; k < 64; k++, l++)
 585                                if (p2[k] != 0xffff) {
 586                                        /*
 587                                         * Found one, copy entry for unicode
 588                                         * l with fontpos value p2[k].
 589                                         */
 590                                        err1 = con_insert_unipair(q, l, p2[k]);
 591                                        if (err1) {
 592                                                p->refcount++;
 593                                                *vc->vc_uni_pagedir_loc = p;
 594                                                con_release_unimap(q);
 595                                                kfree(q);
 596                                                console_unlock();
 597                                                return err1; 
 598                                        }
 599                                }
 600                        } else {
 601                                /* Account for row of 64 empty entries */
 602                                l += 64;
 603                        }
 604                }
 605                else
 606                        /* Account for empty table */
 607                        l += 32 * 64;
 608                }
 609
 610                /*
 611                 * Finished copying font table, set vc_uni_pagedir to new table
 612                 */
 613                p = q;
 614        } else if (p == dflt) {
 615                dflt = NULL;
 616        }
 617
 618        /*
 619         * Insert user specified unicode pairs into new table.
 620         */
 621        while (ct--) {
 622                unsigned short unicode, fontpos;
 623                __get_user(unicode, &list->unicode);
 624                __get_user(fontpos, &list->fontpos);
 625                if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
 626                        err = err1;
 627                list++;
 628        }
 629        
 630        /*
 631         * Merge with fontmaps of any other virtual consoles.
 632         */
 633        if (con_unify_unimap(vc, p)) {
 634                console_unlock();
 635                return err;
 636        }
 637
 638        for (i = 0; i <= 3; i++)
 639                set_inverse_transl(vc, p, i); /* Update inverse translations */
 640        set_inverse_trans_unicode(vc, p);
 641
 642out_unlock:
 643        console_unlock();
 644        return err;
 645}
 646
 647/**
 648 *      con_set_default_unimap  -       set default unicode map
 649 *      @vc: the console we are updating
 650 *
 651 *      Loads the unimap for the hardware font, as defined in uni_hash.tbl.
 652 *      The representation used was the most compact I could come up
 653 *      with.  This routine is executed at video setup, and when the
 654 *      PIO_FONTRESET ioctl is called. 
 655 *
 656 *      The caller must hold the console lock
 657 */
 658int con_set_default_unimap(struct vc_data *vc)
 659{
 660        int i, j, err = 0, err1;
 661        u16 *q;
 662        struct uni_pagedir *p;
 663
 664        if (dflt) {
 665                p = *vc->vc_uni_pagedir_loc;
 666                if (p == dflt)
 667                        return 0;
 668
 669                dflt->refcount++;
 670                *vc->vc_uni_pagedir_loc = dflt;
 671                if (p && !--p->refcount) {
 672                        con_release_unimap(p);
 673                        kfree(p);
 674                }
 675                return 0;
 676        }
 677        
 678        /* The default font is always 256 characters */
 679
 680        err = con_do_clear_unimap(vc, NULL);
 681        if (err)
 682                return err;
 683    
 684        p = *vc->vc_uni_pagedir_loc;
 685        q = dfont_unitable;
 686        
 687        for (i = 0; i < 256; i++)
 688                for (j = dfont_unicount[i]; j; j--) {
 689                        err1 = con_insert_unipair(p, *(q++), i);
 690                        if (err1)
 691                                err = err1;
 692                }
 693                        
 694        if (con_unify_unimap(vc, p)) {
 695                dflt = *vc->vc_uni_pagedir_loc;
 696                return err;
 697        }
 698
 699        for (i = 0; i <= 3; i++)
 700                set_inverse_transl(vc, p, i);   /* Update all inverse translations */
 701        set_inverse_trans_unicode(vc, p);
 702        dflt = p;
 703        return err;
 704}
 705EXPORT_SYMBOL(con_set_default_unimap);
 706
 707/**
 708 *      con_copy_unimap         -       copy unimap between two vts
 709 *      @dst_vc: target
 710 *      @src_vt: source
 711 *
 712 *      The caller must hold the console lock when invoking this method
 713 */
 714int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
 715{
 716        struct uni_pagedir *q;
 717
 718        if (!*src_vc->vc_uni_pagedir_loc)
 719                return -EINVAL;
 720        if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
 721                return 0;
 722        con_free_unimap(dst_vc);
 723        q = *src_vc->vc_uni_pagedir_loc;
 724        q->refcount++;
 725        *dst_vc->vc_uni_pagedir_loc = q;
 726        return 0;
 727}
 728EXPORT_SYMBOL(con_copy_unimap);
 729
 730/**
 731 *      con_get_unimap          -       get the unicode map
 732 *      @vc: the console to read from
 733 *
 734 *      Read the console unicode data for this console. Called from the ioctl
 735 *      handlers.
 736 */
 737int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
 738{
 739        int i, j, k, ect;
 740        u16 **p1, *p2;
 741        struct uni_pagedir *p;
 742
 743        console_lock();
 744
 745        ect = 0;
 746        if (*vc->vc_uni_pagedir_loc) {
 747                p = *vc->vc_uni_pagedir_loc;
 748                for (i = 0; i < 32; i++) {
 749                p1 = p->uni_pgdir[i];
 750                if (p1)
 751                        for (j = 0; j < 32; j++) {
 752                        p2 = *(p1++);
 753                        if (p2)
 754                                for (k = 0; k < 64; k++) {
 755                                        if (*p2 < MAX_GLYPH && ect++ < ct) {
 756                                                __put_user((u_short)((i<<11)+(j<<6)+k),
 757                                                           &list->unicode);
 758                                                __put_user((u_short) *p2, 
 759                                                           &list->fontpos);
 760                                                list++;
 761                                        }
 762                                        p2++;
 763                                }
 764                        }
 765                }
 766        }
 767        __put_user(ect, uct);
 768        console_unlock();
 769        return ((ect <= ct) ? 0 : -ENOMEM);
 770}
 771
 772/*
 773 * Always use USER_MAP. These functions are used by the keyboard,
 774 * which shouldn't be affected by G0/G1 switching, etc.
 775 * If the user map still contains default values, i.e. the
 776 * direct-to-font mapping, then assume user is using Latin1.
 777 *
 778 * FIXME: at some point we need to decide if we want to lock the table
 779 * update element itself via the keyboard_event_lock for consistency with the
 780 * keyboard driver as well as the consoles
 781 */
 782/* may be called during an interrupt */
 783u32 conv_8bit_to_uni(unsigned char c)
 784{
 785        unsigned short uni = translations[USER_MAP][c];
 786        return uni == (0xf000 | c) ? c : uni;
 787}
 788
 789int conv_uni_to_8bit(u32 uni)
 790{
 791        int c;
 792        for (c = 0; c < 0x100; c++)
 793                if (translations[USER_MAP][c] == uni ||
 794                   (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
 795                        return c;
 796        return -1;
 797}
 798
 799int
 800conv_uni_to_pc(struct vc_data *conp, long ucs) 
 801{
 802        int h;
 803        u16 **p1, *p2;
 804        struct uni_pagedir *p;
 805  
 806        /* Only 16-bit codes supported at this time */
 807        if (ucs > 0xffff)
 808                return -4;              /* Not found */
 809        else if (ucs < 0x20)
 810                return -1;              /* Not a printable character */
 811        else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
 812                return -2;                      /* Zero-width space */
 813        /*
 814         * UNI_DIRECT_BASE indicates the start of the region in the User Zone
 815         * which always has a 1:1 mapping to the currently loaded font.  The
 816         * UNI_DIRECT_MASK indicates the bit span of the region.
 817         */
 818        else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
 819                return ucs & UNI_DIRECT_MASK;
 820  
 821        if (!*conp->vc_uni_pagedir_loc)
 822                return -3;
 823
 824        p = *conp->vc_uni_pagedir_loc;
 825        if ((p1 = p->uni_pgdir[ucs >> 11]) &&
 826            (p2 = p1[(ucs >> 6) & 0x1f]) &&
 827            (h = p2[ucs & 0x3f]) < MAX_GLYPH)
 828                return h;
 829
 830        return -4;              /* not found */
 831}
 832
 833/*
 834 * This is called at sys_setup time, after memory and the console are
 835 * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
 836 * from this function, hence the call from sys_setup.
 837 */
 838void __init 
 839console_map_init(void)
 840{
 841        int i;
 842        
 843        for (i = 0; i < MAX_NR_CONSOLES; i++)
 844                if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
 845                        con_set_default_unimap(vc_cons[i].d);
 846}
 847
 848