Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * consolemap.c
0004  *
0005  * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
0006  * to font positions.
0007  *
0008  * aeb, 950210
0009  *
0010  * Support for multiple unimaps by Jakub Jelinek <jj@ultra.linux.cz>, July 1998
0011  *
0012  * Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
0013  *
0014  * In order to prevent the following circular lock dependency:
0015  *   &mm->mmap_lock --> cpu_hotplug.lock --> console_lock --> &mm->mmap_lock
0016  *
0017  * We cannot allow page fault to happen while holding the console_lock.
0018  * Therefore, all the userspace copy operations have to be done outside
0019  * the console_lock critical sections.
0020  *
0021  * As all the affected functions are all called directly from vt_ioctl(), we
0022  * can allocate some small buffers directly on stack without worrying about
0023  * stack overflow.
0024  */
0025 
0026 #include <linux/bitfield.h>
0027 #include <linux/bits.h>
0028 #include <linux/module.h>
0029 #include <linux/kd.h>
0030 #include <linux/errno.h>
0031 #include <linux/mm.h>
0032 #include <linux/slab.h>
0033 #include <linux/init.h>
0034 #include <linux/tty.h>
0035 #include <linux/uaccess.h>
0036 #include <linux/console.h>
0037 #include <linux/consolemap.h>
0038 #include <linux/vt_kern.h>
0039 #include <linux/string.h>
0040 
0041 static unsigned short translations[][E_TABSZ] = {
0042   /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
0043   [LAT1_MAP] = {
0044     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0045     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0046     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0047     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0048     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0049     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0050     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0051     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0052     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0053     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0054     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0055     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0056     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0057     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0058     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0059     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0060     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
0061     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
0062     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
0063     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
0064     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
0065     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
0066     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
0067     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
0068     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
0069     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
0070     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
0071     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
0072     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
0073     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
0074     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
0075     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
0076   },
0077   /* VT100 graphics mapped to Unicode */
0078   [GRAF_MAP] = {
0079     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0080     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0081     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0082     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0083     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0084     0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
0085     0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0086     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0087     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0088     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0089     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0090     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
0091     0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
0092     0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
0093     0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
0094     0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
0095     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
0096     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
0097     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
0098     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
0099     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
0100     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
0101     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
0102     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
0103     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
0104     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
0105     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
0106     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
0107     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
0108     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
0109     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
0110     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
0111   },
0112   /* IBM Codepage 437 mapped to Unicode */
0113   [IBMPC_MAP] = {
0114     0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
0115     0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
0116     0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
0117     0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
0118     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0119     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0120     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0121     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0122     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0123     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0124     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0125     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0126     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0127     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0128     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0129     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
0130     0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
0131     0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
0132     0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
0133     0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
0134     0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
0135     0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
0136     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0137     0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
0138     0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
0139     0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
0140     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
0141     0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
0142     0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
0143     0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
0144     0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
0145     0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
0146   },
0147   /* User mapping -- default to codes for direct font mapping */
0148   [USER_MAP] = {
0149     0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
0150     0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
0151     0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
0152     0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
0153     0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
0154     0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
0155     0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
0156     0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
0157     0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
0158     0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
0159     0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
0160     0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
0161     0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
0162     0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
0163     0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
0164     0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
0165     0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
0166     0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
0167     0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
0168     0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
0169     0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
0170     0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
0171     0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
0172     0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
0173     0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
0174     0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
0175     0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
0176     0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
0177     0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
0178     0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
0179     0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
0180     0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
0181   }
0182 };
0183 
0184 /* The standard kernel character-to-font mappings are not invertible
0185    -- this is just a best effort. */
0186 
0187 #define MAX_GLYPH 512       /* Max possible glyph value */
0188 
0189 static enum translation_map inv_translate[MAX_NR_CONSOLES];
0190 
0191 #define UNI_DIRS    32U
0192 #define UNI_DIR_ROWS    32U
0193 #define UNI_ROW_GLYPHS  64U
0194 
0195 #define UNI_DIR_BITS        GENMASK(15, 11)
0196 #define UNI_ROW_BITS        GENMASK(10,  6)
0197 #define UNI_GLYPH_BITS      GENMASK( 5,  0)
0198 
0199 #define UNI_DIR(uni)        FIELD_GET(UNI_DIR_BITS, (uni))
0200 #define UNI_ROW(uni)        FIELD_GET(UNI_ROW_BITS, (uni))
0201 #define UNI_GLYPH(uni)      FIELD_GET(UNI_GLYPH_BITS, (uni))
0202 
0203 #define UNI(dir, row, glyph)    (FIELD_PREP(UNI_DIR_BITS, (dir)) | \
0204                  FIELD_PREP(UNI_ROW_BITS, (row)) | \
0205                  FIELD_PREP(UNI_GLYPH_BITS, (glyph)))
0206 
0207 /**
0208  * struct uni_pagedict -- unicode directory
0209  *
0210  * @uni_pgdir: 32*32*64 table with glyphs
0211  * @refcount: reference count of this structure
0212  * @sum: checksum
0213  * @inverse_translations: best-effort inverse mapping
0214  * @inverse_trans_unicode: best-effort inverse mapping to unicode
0215  */
0216 struct uni_pagedict {
0217     u16     **uni_pgdir[UNI_DIRS];
0218     unsigned long   refcount;
0219     unsigned long   sum;
0220     unsigned char   *inverse_translations[LAST_MAP + 1];
0221     u16     *inverse_trans_unicode;
0222 };
0223 
0224 static struct uni_pagedict *dflt;
0225 
0226 static void set_inverse_transl(struct vc_data *conp, struct uni_pagedict *dict,
0227            enum translation_map m)
0228 {
0229     unsigned short *t = translations[m];
0230     unsigned char *inv;
0231 
0232     if (!dict)
0233         return;
0234     inv = dict->inverse_translations[m];
0235 
0236     if (!inv) {
0237         inv = dict->inverse_translations[m] = kmalloc(MAX_GLYPH,
0238                 GFP_KERNEL);
0239         if (!inv)
0240             return;
0241     }
0242     memset(inv, 0, MAX_GLYPH);
0243 
0244     for (unsigned int ch = 0; ch < ARRAY_SIZE(translations[m]); ch++) {
0245         int glyph = conv_uni_to_pc(conp, t[ch]);
0246         if (glyph >= 0 && glyph < MAX_GLYPH && inv[glyph] < 32) {
0247             /* prefer '-' above SHY etc. */
0248             inv[glyph] = ch;
0249         }
0250     }
0251 }
0252 
0253 static void set_inverse_trans_unicode(struct uni_pagedict *dict)
0254 {
0255     unsigned int d, r, g;
0256     u16 *inv;
0257 
0258     if (!dict)
0259         return;
0260 
0261     inv = dict->inverse_trans_unicode;
0262     if (!inv) {
0263         inv = dict->inverse_trans_unicode = kmalloc_array(MAX_GLYPH,
0264                 sizeof(*inv), GFP_KERNEL);
0265         if (!inv)
0266             return;
0267     }
0268     memset(inv, 0, MAX_GLYPH * sizeof(*inv));
0269 
0270     for (d = 0; d < UNI_DIRS; d++) {
0271         u16 **dir = dict->uni_pgdir[d];
0272         if (!dir)
0273             continue;
0274         for (r = 0; r < UNI_DIR_ROWS; r++) {
0275             u16 *row = dir[r];
0276             if (!row)
0277                 continue;
0278             for (g = 0; g < UNI_ROW_GLYPHS; g++) {
0279                 u16 glyph = row[g];
0280                 if (glyph < MAX_GLYPH && inv[glyph] < 32)
0281                     inv[glyph] = UNI(d, r, g);
0282             }
0283         }
0284     }
0285 }
0286 
0287 unsigned short *set_translate(enum translation_map m, struct vc_data *vc)
0288 {
0289     inv_translate[vc->vc_num] = m;
0290     return translations[m];
0291 }
0292 
0293 /*
0294  * Inverse translation is impossible for several reasons:
0295  * 1. The font<->character maps are not 1-1.
0296  * 2. The text may have been written while a different translation map
0297  *    was active.
0298  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
0299  */
0300 u16 inverse_translate(const struct vc_data *conp, u16 glyph, bool use_unicode)
0301 {
0302     struct uni_pagedict *p;
0303     enum translation_map m;
0304 
0305     if (glyph >= MAX_GLYPH)
0306         return 0;
0307 
0308     p = *conp->uni_pagedict_loc;
0309     if (!p)
0310         return glyph;
0311 
0312     if (use_unicode) {
0313         if (!p->inverse_trans_unicode)
0314             return glyph;
0315 
0316         return p->inverse_trans_unicode[glyph];
0317     }
0318 
0319     m = inv_translate[conp->vc_num];
0320     if (!p->inverse_translations[m])
0321         return glyph;
0322 
0323     return p->inverse_translations[m][glyph];
0324 }
0325 EXPORT_SYMBOL_GPL(inverse_translate);
0326 
0327 static void update_user_maps(void)
0328 {
0329     int i;
0330     struct uni_pagedict *p, *q = NULL;
0331 
0332     for (i = 0; i < MAX_NR_CONSOLES; i++) {
0333         if (!vc_cons_allocated(i))
0334             continue;
0335         p = *vc_cons[i].d->uni_pagedict_loc;
0336         if (p && p != q) {
0337             set_inverse_transl(vc_cons[i].d, p, USER_MAP);
0338             set_inverse_trans_unicode(p);
0339             q = p;
0340         }
0341     }
0342 }
0343 
0344 /*
0345  * Load customizable translation table
0346  * arg points to a 256 byte translation table.
0347  *
0348  * The "old" variants are for translation directly to font (using the
0349  * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
0350  * Unicodes explicitly.
0351  */
0352 int con_set_trans_old(unsigned char __user * arg)
0353 {
0354     unsigned short inbuf[E_TABSZ];
0355     unsigned int i;
0356     unsigned char ch;
0357 
0358     for (i = 0; i < ARRAY_SIZE(inbuf); i++) {
0359         if (get_user(ch, &arg[i]))
0360             return -EFAULT;
0361         inbuf[i] = UNI_DIRECT_BASE | ch;
0362     }
0363 
0364     console_lock();
0365     memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
0366     update_user_maps();
0367     console_unlock();
0368     return 0;
0369 }
0370 
0371 int con_get_trans_old(unsigned char __user * arg)
0372 {
0373     int i, ch;
0374     unsigned short *p = translations[USER_MAP];
0375     unsigned char outbuf[E_TABSZ];
0376 
0377     console_lock();
0378     for (i = 0; i < ARRAY_SIZE(outbuf); i++)
0379     {
0380         ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
0381         outbuf[i] = (ch & ~0xff) ? 0 : ch;
0382     }
0383     console_unlock();
0384 
0385     return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 0;
0386 }
0387 
0388 int con_set_trans_new(ushort __user * arg)
0389 {
0390     unsigned short inbuf[E_TABSZ];
0391 
0392     if (copy_from_user(inbuf, arg, sizeof(inbuf)))
0393         return -EFAULT;
0394 
0395     console_lock();
0396     memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
0397     update_user_maps();
0398     console_unlock();
0399     return 0;
0400 }
0401 
0402 int con_get_trans_new(ushort __user * arg)
0403 {
0404     unsigned short outbuf[E_TABSZ];
0405 
0406     console_lock();
0407     memcpy(outbuf, translations[USER_MAP], sizeof(outbuf));
0408     console_unlock();
0409 
0410     return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 0;
0411 }
0412 
0413 /*
0414  * Unicode -> current font conversion
0415  *
0416  * A font has at most 512 chars, usually 256.
0417  * But one font position may represent several Unicode chars.
0418  * A hashtable is somewhat of a pain to deal with, so use a
0419  * "paged table" instead.  Simulation has shown the memory cost of
0420  * this 3-level paged table scheme to be comparable to a hash table.
0421  */
0422 
0423 extern u8 dfont_unicount[]; /* Defined in console_defmap.c */
0424 extern u16 dfont_unitable[];
0425 
0426 static void con_release_unimap(struct uni_pagedict *dict)
0427 {
0428     unsigned int d, r;
0429 
0430     if (dict == dflt)
0431         dflt = NULL;
0432 
0433     for (d = 0; d < UNI_DIRS; d++) {
0434         u16 **dir = dict->uni_pgdir[d];
0435         if (dir != NULL) {
0436             for (r = 0; r < UNI_DIR_ROWS; r++)
0437                 kfree(dir[r]);
0438             kfree(dir);
0439         }
0440         dict->uni_pgdir[d] = NULL;
0441     }
0442 
0443     for (r = 0; r < ARRAY_SIZE(dict->inverse_translations); r++) {
0444         kfree(dict->inverse_translations[r]);
0445         dict->inverse_translations[r] = NULL;
0446     }
0447 
0448     kfree(dict->inverse_trans_unicode);
0449     dict->inverse_trans_unicode = NULL;
0450 }
0451 
0452 /* Caller must hold the console lock */
0453 void con_free_unimap(struct vc_data *vc)
0454 {
0455     struct uni_pagedict *p;
0456 
0457     p = *vc->uni_pagedict_loc;
0458     if (!p)
0459         return;
0460     *vc->uni_pagedict_loc = NULL;
0461     if (--p->refcount)
0462         return;
0463     con_release_unimap(p);
0464     kfree(p);
0465 }
0466 
0467 static int con_unify_unimap(struct vc_data *conp, struct uni_pagedict *dict1)
0468 {
0469     struct uni_pagedict *dict2;
0470     unsigned int cons, d, r;
0471 
0472     for (cons = 0; cons < MAX_NR_CONSOLES; cons++) {
0473         if (!vc_cons_allocated(cons))
0474             continue;
0475         dict2 = *vc_cons[cons].d->uni_pagedict_loc;
0476         if (!dict2 || dict2 == dict1 || dict2->sum != dict1->sum)
0477             continue;
0478         for (d = 0; d < UNI_DIRS; d++) {
0479             u16 **dir1 = dict1->uni_pgdir[d];
0480             u16 **dir2 = dict2->uni_pgdir[d];
0481             if (!dir1 && !dir2)
0482                 continue;
0483             if (!dir1 || !dir2)
0484                 break;
0485             for (r = 0; r < UNI_DIR_ROWS; r++) {
0486                 if (!dir1[r] && !dir2[r])
0487                     continue;
0488                 if (!dir1[r] || !dir2[r])
0489                     break;
0490                 if (memcmp(dir1[r], dir2[r], UNI_ROW_GLYPHS *
0491                             sizeof(*dir1[r])))
0492                     break;
0493             }
0494             if (r < UNI_DIR_ROWS)
0495                 break;
0496         }
0497         if (d == UNI_DIRS) {
0498             dict2->refcount++;
0499             *conp->uni_pagedict_loc = dict2;
0500             con_release_unimap(dict1);
0501             kfree(dict1);
0502             return 1;
0503         }
0504     }
0505     return 0;
0506 }
0507 
0508 static int
0509 con_insert_unipair(struct uni_pagedict *p, u_short unicode, u_short fontpos)
0510 {
0511     u16 **dir, *row;
0512     unsigned int n;
0513 
0514     n = UNI_DIR(unicode);
0515     dir = p->uni_pgdir[n];
0516     if (!dir) {
0517         dir = p->uni_pgdir[n] = kcalloc(UNI_DIR_ROWS, sizeof(*dir),
0518                 GFP_KERNEL);
0519         if (!dir)
0520             return -ENOMEM;
0521     }
0522 
0523     n = UNI_ROW(unicode);
0524     row = dir[n];
0525     if (!row) {
0526         row = dir[n] = kmalloc_array(UNI_ROW_GLYPHS, sizeof(*row),
0527                 GFP_KERNEL);
0528         if (!row)
0529             return -ENOMEM;
0530         /* No glyphs for the characters (yet) */
0531         memset(row, 0xff, UNI_ROW_GLYPHS * sizeof(*row));
0532     }
0533 
0534     row[UNI_GLYPH(unicode)] = fontpos;
0535 
0536     p->sum += (fontpos << 20U) + unicode;
0537 
0538     return 0;
0539 }
0540 
0541 static int con_allocate_new(struct vc_data *vc)
0542 {
0543     struct uni_pagedict *new, *old = *vc->uni_pagedict_loc;
0544 
0545     new = kzalloc(sizeof(*new), GFP_KERNEL);
0546     if (!new)
0547         return -ENOMEM;
0548 
0549     new->refcount = 1;
0550     *vc->uni_pagedict_loc = new;
0551 
0552     if (old)
0553         old->refcount--;
0554 
0555     return 0;
0556 }
0557 
0558 /* Caller must hold the lock */
0559 static int con_do_clear_unimap(struct vc_data *vc)
0560 {
0561     struct uni_pagedict *old = *vc->uni_pagedict_loc;
0562 
0563     if (!old || old->refcount > 1)
0564         return con_allocate_new(vc);
0565 
0566     old->sum = 0;
0567     con_release_unimap(old);
0568 
0569     return 0;
0570 }
0571 
0572 int con_clear_unimap(struct vc_data *vc)
0573 {
0574     int ret;
0575     console_lock();
0576     ret = con_do_clear_unimap(vc);
0577     console_unlock();
0578     return ret;
0579 }
0580 
0581 static struct uni_pagedict *con_unshare_unimap(struct vc_data *vc,
0582         struct uni_pagedict *old)
0583 {
0584     struct uni_pagedict *new;
0585     unsigned int d, r, g;
0586     int ret;
0587     u16 uni = 0;
0588 
0589     ret = con_allocate_new(vc);
0590     if (ret)
0591         return ERR_PTR(ret);
0592 
0593     new = *vc->uni_pagedict_loc;
0594 
0595     /*
0596      * uni_pgdir is a 32*32*64 table with rows allocated when its first
0597      * entry is added. The unicode value must still be incremented for
0598      * empty rows. We are copying entries from "old" to "new".
0599      */
0600     for (d = 0; d < UNI_DIRS; d++) {
0601         u16 **dir = old->uni_pgdir[d];
0602         if (!dir) {
0603             /* Account for empty table */
0604             uni += UNI_DIR_ROWS * UNI_ROW_GLYPHS;
0605             continue;
0606         }
0607 
0608         for (r = 0; r < UNI_DIR_ROWS; r++) {
0609             u16 *row = dir[r];
0610             if (!row) {
0611                 /* Account for row of 64 empty entries */
0612                 uni += UNI_ROW_GLYPHS;
0613                 continue;
0614             }
0615 
0616             for (g = 0; g < UNI_ROW_GLYPHS; g++, uni++) {
0617                 if (row[g] == 0xffff)
0618                     continue;
0619                 /*
0620                  * Found one, copy entry for unicode uni with
0621                  * fontpos value row[g].
0622                  */
0623                 ret = con_insert_unipair(new, uni, row[g]);
0624                 if (ret) {
0625                     old->refcount++;
0626                     *vc->uni_pagedict_loc = old;
0627                     con_release_unimap(new);
0628                     kfree(new);
0629                     return ERR_PTR(ret);
0630                 }
0631             }
0632         }
0633     }
0634 
0635     return new;
0636 }
0637 
0638 int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
0639 {
0640     int err = 0, err1;
0641     struct uni_pagedict *dict;
0642     struct unipair *unilist, *plist;
0643 
0644     if (!ct)
0645         return 0;
0646 
0647     unilist = vmemdup_user(list, array_size(sizeof(*unilist), ct));
0648     if (IS_ERR(unilist))
0649         return PTR_ERR(unilist);
0650 
0651     console_lock();
0652 
0653     /* Save original vc_unipagdir_loc in case we allocate a new one */
0654     dict = *vc->uni_pagedict_loc;
0655     if (!dict) {
0656         err = -EINVAL;
0657         goto out_unlock;
0658     }
0659 
0660     if (dict->refcount > 1) {
0661         dict = con_unshare_unimap(vc, dict);
0662         if (IS_ERR(dict)) {
0663             err = PTR_ERR(dict);
0664             goto out_unlock;
0665         }
0666     } else if (dict == dflt) {
0667         dflt = NULL;
0668     }
0669 
0670     /*
0671      * Insert user specified unicode pairs into new table.
0672      */
0673     for (plist = unilist; ct; ct--, plist++) {
0674         err1 = con_insert_unipair(dict, plist->unicode, plist->fontpos);
0675         if (err1)
0676             err = err1;
0677     }
0678 
0679     /*
0680      * Merge with fontmaps of any other virtual consoles.
0681      */
0682     if (con_unify_unimap(vc, dict))
0683         goto out_unlock;
0684 
0685     for (enum translation_map m = FIRST_MAP; m <= LAST_MAP; m++)
0686         set_inverse_transl(vc, dict, m);
0687     set_inverse_trans_unicode(dict);
0688 
0689 out_unlock:
0690     console_unlock();
0691     kvfree(unilist);
0692     return err;
0693 }
0694 
0695 /**
0696  *  con_set_default_unimap  -   set default unicode map
0697  *  @vc: the console we are updating
0698  *
0699  *  Loads the unimap for the hardware font, as defined in uni_hash.tbl.
0700  *  The representation used was the most compact I could come up
0701  *  with.  This routine is executed at video setup, and when the
0702  *  PIO_FONTRESET ioctl is called.
0703  *
0704  *  The caller must hold the console lock
0705  */
0706 int con_set_default_unimap(struct vc_data *vc)
0707 {
0708     struct uni_pagedict *dict;
0709     unsigned int fontpos, count;
0710     int err = 0, err1;
0711     u16 *dfont;
0712 
0713     if (dflt) {
0714         dict = *vc->uni_pagedict_loc;
0715         if (dict == dflt)
0716             return 0;
0717 
0718         dflt->refcount++;
0719         *vc->uni_pagedict_loc = dflt;
0720         if (dict && !--dict->refcount) {
0721             con_release_unimap(dict);
0722             kfree(dict);
0723         }
0724         return 0;
0725     }
0726 
0727     /* The default font is always 256 characters */
0728 
0729     err = con_do_clear_unimap(vc);
0730     if (err)
0731         return err;
0732 
0733     dict = *vc->uni_pagedict_loc;
0734     dfont = dfont_unitable;
0735 
0736     for (fontpos = 0; fontpos < 256U; fontpos++)
0737         for (count = dfont_unicount[fontpos]; count; count--) {
0738             err1 = con_insert_unipair(dict, *(dfont++), fontpos);
0739             if (err1)
0740                 err = err1;
0741         }
0742 
0743     if (con_unify_unimap(vc, dict)) {
0744         dflt = *vc->uni_pagedict_loc;
0745         return err;
0746     }
0747 
0748     for (enum translation_map m = FIRST_MAP; m <= LAST_MAP; m++)
0749         set_inverse_transl(vc, dict, m);
0750     set_inverse_trans_unicode(dict);
0751     dflt = dict;
0752     return err;
0753 }
0754 EXPORT_SYMBOL(con_set_default_unimap);
0755 
0756 /**
0757  *  con_copy_unimap     -   copy unimap between two vts
0758  *  @dst_vc: target
0759  *  @src_vc: source
0760  *
0761  *  The caller must hold the console lock when invoking this method
0762  */
0763 int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
0764 {
0765     struct uni_pagedict *src;
0766 
0767     if (!*src_vc->uni_pagedict_loc)
0768         return -EINVAL;
0769     if (*dst_vc->uni_pagedict_loc == *src_vc->uni_pagedict_loc)
0770         return 0;
0771     con_free_unimap(dst_vc);
0772     src = *src_vc->uni_pagedict_loc;
0773     src->refcount++;
0774     *dst_vc->uni_pagedict_loc = src;
0775     return 0;
0776 }
0777 EXPORT_SYMBOL(con_copy_unimap);
0778 
0779 /*
0780  *  con_get_unimap      -   get the unicode map
0781  *
0782  *  Read the console unicode data for this console. Called from the ioctl
0783  *  handlers.
0784  */
0785 int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct,
0786         struct unipair __user *list)
0787 {
0788     ushort ect;
0789     struct uni_pagedict *dict;
0790     struct unipair *unilist;
0791     unsigned int d, r, g;
0792     int ret = 0;
0793 
0794     unilist = kvmalloc_array(ct, sizeof(*unilist), GFP_KERNEL);
0795     if (!unilist)
0796         return -ENOMEM;
0797 
0798     console_lock();
0799 
0800     ect = 0;
0801     dict = *vc->uni_pagedict_loc;
0802     if (!dict)
0803         goto unlock;
0804 
0805     for (d = 0; d < UNI_DIRS; d++) {
0806         u16 **dir = dict->uni_pgdir[d];
0807         if (!dir)
0808             continue;
0809 
0810         for (r = 0; r < UNI_DIR_ROWS; r++) {
0811             u16 *row = dir[r];
0812             if (!row)
0813                 continue;
0814 
0815             for (g = 0; g < UNI_ROW_GLYPHS; g++, row++) {
0816                 if (*row >= MAX_GLYPH)
0817                     continue;
0818                 if (ect < ct) {
0819                     unilist[ect].unicode = UNI(d, r, g);
0820                     unilist[ect].fontpos = *row;
0821                 }
0822                 ect++;
0823             }
0824         }
0825     }
0826 unlock:
0827     console_unlock();
0828     if (copy_to_user(list, unilist, min(ect, ct) * sizeof(*unilist)))
0829         ret = -EFAULT;
0830     if (put_user(ect, uct))
0831         ret = -EFAULT;
0832     kvfree(unilist);
0833     return ret ? ret : (ect <= ct) ? 0 : -ENOMEM;
0834 }
0835 
0836 /*
0837  * Always use USER_MAP. These functions are used by the keyboard,
0838  * which shouldn't be affected by G0/G1 switching, etc.
0839  * If the user map still contains default values, i.e. the
0840  * direct-to-font mapping, then assume user is using Latin1.
0841  *
0842  * FIXME: at some point we need to decide if we want to lock the table
0843  * update element itself via the keyboard_event_lock for consistency with the
0844  * keyboard driver as well as the consoles
0845  */
0846 /* may be called during an interrupt */
0847 u32 conv_8bit_to_uni(unsigned char c)
0848 {
0849     unsigned short uni = translations[USER_MAP][c];
0850     return uni == (0xf000 | c) ? c : uni;
0851 }
0852 
0853 int conv_uni_to_8bit(u32 uni)
0854 {
0855     int c;
0856     for (c = 0; c < ARRAY_SIZE(translations[USER_MAP]); c++)
0857         if (translations[USER_MAP][c] == uni ||
0858            (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
0859             return c;
0860     return -1;
0861 }
0862 
0863 int conv_uni_to_pc(struct vc_data *conp, long ucs)
0864 {
0865     struct uni_pagedict *dict;
0866     u16 **dir, *row, glyph;
0867 
0868     /* Only 16-bit codes supported at this time */
0869     if (ucs > 0xffff)
0870         return -4;      /* Not found */
0871     else if (ucs < 0x20)
0872         return -1;      /* Not a printable character */
0873     else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
0874         return -2;          /* Zero-width space */
0875     /*
0876      * UNI_DIRECT_BASE indicates the start of the region in the User Zone
0877      * which always has a 1:1 mapping to the currently loaded font.  The
0878      * UNI_DIRECT_MASK indicates the bit span of the region.
0879      */
0880     else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
0881         return ucs & UNI_DIRECT_MASK;
0882 
0883     dict = *conp->uni_pagedict_loc;
0884     if (!dict)
0885         return -3;
0886 
0887     dir = dict->uni_pgdir[UNI_DIR(ucs)];
0888     if (!dir)
0889         return -4;
0890 
0891     row = dir[UNI_ROW(ucs)];
0892     if (!row)
0893         return -4;
0894 
0895     glyph = row[UNI_GLYPH(ucs)];
0896     if (glyph >= MAX_GLYPH)
0897         return -4;
0898 
0899     return glyph;
0900 }
0901 
0902 /*
0903  * This is called at sys_setup time, after memory and the console are
0904  * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
0905  * from this function, hence the call from sys_setup.
0906  */
0907 void __init
0908 console_map_init(void)
0909 {
0910     int i;
0911 
0912     for (i = 0; i < MAX_NR_CONSOLES; i++)
0913         if (vc_cons_allocated(i) && !*vc_cons[i].d->uni_pagedict_loc)
0914             con_set_default_unimap(vc_cons[i].d);
0915 }
0916