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