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