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