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