xref: /linux/drivers/tty/vt/consolemap.c (revision 0d456bad36d42d16022be045c8a53ddbb59ee478)
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 	int		readonly;
183 };
184 
185 static struct uni_pagedir *dflt;
186 
187 static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
188 {
189 	int j, glyph;
190 	unsigned short *t = translations[i];
191 	unsigned char *q;
192 
193 	if (!p) return;
194 	q = p->inverse_translations[i];
195 
196 	if (!q) {
197 		q = p->inverse_translations[i] = (unsigned char *)
198 			kmalloc(MAX_GLYPH, GFP_KERNEL);
199 		if (!q) return;
200 	}
201 	memset(q, 0, MAX_GLYPH);
202 
203 	for (j = 0; j < E_TABSZ; j++) {
204 		glyph = conv_uni_to_pc(conp, t[j]);
205 		if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
206 			/* prefer '-' above SHY etc. */
207 		  	q[glyph] = j;
208 		}
209 	}
210 }
211 
212 static void set_inverse_trans_unicode(struct vc_data *conp,
213 				      struct uni_pagedir *p)
214 {
215 	int i, j, k, glyph;
216 	u16 **p1, *p2;
217 	u16 *q;
218 
219 	if (!p) return;
220 	q = p->inverse_trans_unicode;
221 	if (!q) {
222 		q = p->inverse_trans_unicode =
223 			kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
224 		if (!q)
225 			return;
226 	}
227 	memset(q, 0, MAX_GLYPH * sizeof(u16));
228 
229 	for (i = 0; i < 32; i++) {
230 		p1 = p->uni_pgdir[i];
231 		if (!p1)
232 			continue;
233 		for (j = 0; j < 32; j++) {
234 			p2 = p1[j];
235 			if (!p2)
236 				continue;
237 			for (k = 0; k < 64; k++) {
238 				glyph = p2[k];
239 				if (glyph >= 0 && glyph < MAX_GLYPH
240 					       && q[glyph] < 32)
241 		  			q[glyph] = (i << 11) + (j << 6) + k;
242 			}
243 		}
244 	}
245 }
246 
247 unsigned short *set_translate(int m, struct vc_data *vc)
248 {
249 	inv_translate[vc->vc_num] = m;
250 	return translations[m];
251 }
252 
253 /*
254  * Inverse translation is impossible for several reasons:
255  * 1. The font<->character maps are not 1-1.
256  * 2. The text may have been written while a different translation map
257  *    was active.
258  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
259  */
260 u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
261 {
262 	struct uni_pagedir *p;
263 	int m;
264 	if (glyph < 0 || glyph >= MAX_GLYPH)
265 		return 0;
266 	else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc))
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 EXPORT_SYMBOL_GPL(inverse_translate);
282 
283 static void update_user_maps(void)
284 {
285 	int i;
286 	struct uni_pagedir *p, *q = NULL;
287 
288 	for (i = 0; i < MAX_NR_CONSOLES; i++) {
289 		if (!vc_cons_allocated(i))
290 			continue;
291 		p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
292 		if (p && p != q) {
293 			set_inverse_transl(vc_cons[i].d, p, USER_MAP);
294 			set_inverse_trans_unicode(vc_cons[i].d, p);
295 			q = p;
296 		}
297 	}
298 }
299 
300 /*
301  * Load customizable translation table
302  * arg points to a 256 byte translation table.
303  *
304  * The "old" variants are for translation directly to font (using the
305  * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
306  * Unicodes explicitly.
307  */
308 int con_set_trans_old(unsigned char __user * arg)
309 {
310 	int i;
311 	unsigned short *p = translations[USER_MAP];
312 
313 	if (!access_ok(VERIFY_READ, arg, E_TABSZ))
314 		return -EFAULT;
315 
316 	console_lock();
317 	for (i=0; i<E_TABSZ ; i++) {
318 		unsigned char uc;
319 		__get_user(uc, arg+i);
320 		p[i] = UNI_DIRECT_BASE | uc;
321 	}
322 
323 	update_user_maps();
324 	console_unlock();
325 	return 0;
326 }
327 
328 int con_get_trans_old(unsigned char __user * arg)
329 {
330 	int i, ch;
331 	unsigned short *p = translations[USER_MAP];
332 
333 	if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
334 		return -EFAULT;
335 
336 	console_lock();
337 	for (i=0; i<E_TABSZ ; i++)
338 	{
339 		ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
340 		__put_user((ch & ~0xff) ? 0 : ch, arg+i);
341 	}
342 	console_unlock();
343 	return 0;
344 }
345 
346 int con_set_trans_new(ushort __user * arg)
347 {
348 	int i;
349 	unsigned short *p = translations[USER_MAP];
350 
351 	if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
352 		return -EFAULT;
353 
354 	console_lock();
355 	for (i=0; i<E_TABSZ ; i++) {
356 		unsigned short us;
357 		__get_user(us, arg+i);
358 		p[i] = us;
359 	}
360 
361 	update_user_maps();
362 	console_unlock();
363 	return 0;
364 }
365 
366 int con_get_trans_new(ushort __user * arg)
367 {
368 	int i;
369 	unsigned short *p = translations[USER_MAP];
370 
371 	if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
372 		return -EFAULT;
373 
374 	console_lock();
375 	for (i=0; i<E_TABSZ ; i++)
376 	  __put_user(p[i], arg+i);
377 	console_unlock();
378 
379 	return 0;
380 }
381 
382 /*
383  * Unicode -> current font conversion
384  *
385  * A font has at most 512 chars, usually 256.
386  * But one font position may represent several Unicode chars.
387  * A hashtable is somewhat of a pain to deal with, so use a
388  * "paged table" instead.  Simulation has shown the memory cost of
389  * this 3-level paged table scheme to be comparable to a hash table.
390  */
391 
392 extern u8 dfont_unicount[];	/* Defined in console_defmap.c */
393 extern u16 dfont_unitable[];
394 
395 static void con_release_unimap(struct uni_pagedir *p)
396 {
397 	u16 **p1;
398 	int i, j;
399 
400 	if (p == dflt) dflt = NULL;
401 	for (i = 0; i < 32; i++) {
402 		if ((p1 = p->uni_pgdir[i]) != NULL) {
403 			for (j = 0; j < 32; j++)
404 				kfree(p1[j]);
405 			kfree(p1);
406 		}
407 		p->uni_pgdir[i] = NULL;
408 	}
409 	for (i = 0; i < 4; i++) {
410 		kfree(p->inverse_translations[i]);
411 		p->inverse_translations[i] = NULL;
412 	}
413 	kfree(p->inverse_trans_unicode);
414 	p->inverse_trans_unicode = NULL;
415 }
416 
417 /* Caller must hold the console lock */
418 void con_free_unimap(struct vc_data *vc)
419 {
420 	struct uni_pagedir *p;
421 
422 	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
423 	if (!p)
424 		return;
425 	*vc->vc_uni_pagedir_loc = 0;
426 	if (--p->refcount)
427 		return;
428 	con_release_unimap(p);
429 	kfree(p);
430 }
431 
432 static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
433 {
434 	int i, j, k;
435 	struct uni_pagedir *q;
436 
437 	for (i = 0; i < MAX_NR_CONSOLES; i++) {
438 		if (!vc_cons_allocated(i))
439 			continue;
440 		q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
441 		if (!q || q == p || q->sum != p->sum)
442 			continue;
443 		for (j = 0; j < 32; j++) {
444 			u16 **p1, **q1;
445 			p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
446 			if (!p1 && !q1)
447 				continue;
448 			if (!p1 || !q1)
449 				break;
450 			for (k = 0; k < 32; k++) {
451 				if (!p1[k] && !q1[k])
452 					continue;
453 				if (!p1[k] || !q1[k])
454 					break;
455 				if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
456 					break;
457 			}
458 			if (k < 32)
459 				break;
460 		}
461 		if (j == 32) {
462 			q->refcount++;
463 			*conp->vc_uni_pagedir_loc = (unsigned long)q;
464 			con_release_unimap(p);
465 			kfree(p);
466 			return 1;
467 		}
468 	}
469 	return 0;
470 }
471 
472 static int
473 con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
474 {
475 	int i, n;
476 	u16 **p1, *p2;
477 
478 	if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
479 		p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
480 		if (!p1) return -ENOMEM;
481 		for (i = 0; i < 32; i++)
482 			p1[i] = NULL;
483 	}
484 
485 	if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
486 		p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
487 		if (!p2) return -ENOMEM;
488 		memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
489 	}
490 
491 	p2[unicode & 0x3f] = fontpos;
492 
493 	p->sum += (fontpos << 20) + unicode;
494 
495 	return 0;
496 }
497 
498 /* ui is a leftover from using a hashtable, but might be used again
499    Caller must hold the lock */
500 static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
501 {
502 	struct uni_pagedir *p, *q;
503 
504 	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
505 	if (p && p->readonly)
506 		return -EIO;
507 
508 	if (!p || --p->refcount) {
509 		q = kzalloc(sizeof(*p), GFP_KERNEL);
510 		if (!q) {
511 			if (p)
512 				p->refcount++;
513 			return -ENOMEM;
514 		}
515 		q->refcount=1;
516 		*vc->vc_uni_pagedir_loc = (unsigned long)q;
517 	} else {
518 		if (p == dflt) dflt = NULL;
519 		p->refcount++;
520 		p->sum = 0;
521 		con_release_unimap(p);
522 	}
523 	return 0;
524 }
525 
526 int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
527 {
528 	int ret;
529 	console_lock();
530 	ret = con_do_clear_unimap(vc, ui);
531 	console_unlock();
532 	return ret;
533 }
534 
535 int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
536 {
537 	int err = 0, err1, i;
538 	struct uni_pagedir *p, *q;
539 
540 	console_lock();
541 
542 	/* Save original vc_unipagdir_loc in case we allocate a new one */
543 	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
544 	if (p->readonly) {
545 		console_unlock();
546 		return -EIO;
547 	}
548 
549 	if (!ct) {
550 		console_unlock();
551 		return 0;
552 	}
553 
554 	if (p->refcount > 1) {
555 		int j, k;
556 		u16 **p1, *p2, l;
557 
558 		err1 = con_do_clear_unimap(vc, NULL);
559 		if (err1) {
560 			console_unlock();
561 			return err1;
562 		}
563 
564 		/*
565 		 * Since refcount was > 1, con_clear_unimap() allocated a
566 		 * a new uni_pagedir for this vc.  Re: p != q
567 		 */
568 		q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
569 
570 		/*
571 		 * uni_pgdir is a 32*32*64 table with rows allocated
572 		 * when its first entry is added.  The unicode value must
573 		 * still be incremented for empty rows.  We are copying
574 		 * entries from "p" (old) to "q" (new).
575 		 */
576 		l = 0;		/* unicode value */
577 		for (i = 0; i < 32; i++)
578 		if ((p1 = p->uni_pgdir[i]))
579 			for (j = 0; j < 32; j++)
580 			if ((p2 = p1[j])) {
581 				for (k = 0; k < 64; k++, l++)
582 				if (p2[k] != 0xffff) {
583 					/*
584 					 * Found one, copy entry for unicode
585 					 * l with fontpos value p2[k].
586 					 */
587 					err1 = con_insert_unipair(q, l, p2[k]);
588 					if (err1) {
589 						p->refcount++;
590 						*vc->vc_uni_pagedir_loc = (unsigned long)p;
591 						con_release_unimap(q);
592 						kfree(q);
593 						console_unlock();
594 						return err1;
595 					}
596 				}
597 			} else {
598 				/* Account for row of 64 empty entries */
599 				l += 64;
600 			}
601 		else
602 			/* Account for empty table */
603 			l += 32 * 64;
604 
605 		/*
606 		 * Finished copying font table, set vc_uni_pagedir to new table
607 		 */
608 		p = q;
609 	} else if (p == dflt) {
610 		dflt = NULL;
611 	}
612 
613 	/*
614 	 * Insert user specified unicode pairs into new table.
615 	 */
616 	while (ct--) {
617 		unsigned short unicode, fontpos;
618 		__get_user(unicode, &list->unicode);
619 		__get_user(fontpos, &list->fontpos);
620 		if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
621 			err = err1;
622 		list++;
623 	}
624 
625 	/*
626 	 * Merge with fontmaps of any other virtual consoles.
627 	 */
628 	if (con_unify_unimap(vc, p)) {
629 		console_unlock();
630 		return err;
631 	}
632 
633 	for (i = 0; i <= 3; i++)
634 		set_inverse_transl(vc, p, i); /* Update inverse translations */
635 	set_inverse_trans_unicode(vc, p);
636 
637 	console_unlock();
638 	return err;
639 }
640 
641 /**
642  *	con_set_default_unimap	-	set default unicode map
643  *	@vc: the console we are updating
644  *
645  *	Loads the unimap for the hardware font, as defined in uni_hash.tbl.
646  *	The representation used was the most compact I could come up
647  *	with.  This routine is executed at video setup, and when the
648  *	PIO_FONTRESET ioctl is called.
649  *
650  *	The caller must hold the console lock
651  */
652 int con_set_default_unimap(struct vc_data *vc)
653 {
654 	int i, j, err = 0, err1;
655 	u16 *q;
656 	struct uni_pagedir *p;
657 
658 	if (dflt) {
659 		p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
660 		if (p == dflt)
661 			return 0;
662 
663 		dflt->refcount++;
664 		*vc->vc_uni_pagedir_loc = (unsigned long)dflt;
665 		if (p && !--p->refcount) {
666 			con_release_unimap(p);
667 			kfree(p);
668 		}
669 		return 0;
670 	}
671 
672 	/* The default font is always 256 characters */
673 
674 	err = con_do_clear_unimap(vc, NULL);
675 	if (err)
676 		return err;
677 
678 	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
679 	q = dfont_unitable;
680 
681 	for (i = 0; i < 256; i++)
682 		for (j = dfont_unicount[i]; j; j--) {
683 			err1 = con_insert_unipair(p, *(q++), i);
684 			if (err1)
685 				err = err1;
686 		}
687 
688 	if (con_unify_unimap(vc, p)) {
689 		dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
690 		return err;
691 	}
692 
693 	for (i = 0; i <= 3; i++)
694 		set_inverse_transl(vc, p, i);	/* Update all inverse translations */
695 	set_inverse_trans_unicode(vc, p);
696 	dflt = p;
697 	return err;
698 }
699 EXPORT_SYMBOL(con_set_default_unimap);
700 
701 /**
702  *	con_copy_unimap		-	copy unimap between two vts
703  *	@dst_vc: target
704  *	@src_vt: source
705  *
706  *	The caller must hold the console lock when invoking this method
707  */
708 int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
709 {
710 	struct uni_pagedir *q;
711 
712 	if (!*src_vc->vc_uni_pagedir_loc)
713 		return -EINVAL;
714 	if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
715 		return 0;
716 	con_free_unimap(dst_vc);
717 	q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;
718 	q->refcount++;
719 	*dst_vc->vc_uni_pagedir_loc = (long)q;
720 	return 0;
721 }
722 EXPORT_SYMBOL(con_copy_unimap);
723 
724 /**
725  *	con_get_unimap		-	get the unicode map
726  *	@vc: the console to read from
727  *
728  *	Read the console unicode data for this console. Called from the ioctl
729  *	handlers.
730  */
731 int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
732 {
733 	int i, j, k, ect;
734 	u16 **p1, *p2;
735 	struct uni_pagedir *p;
736 
737 	console_lock();
738 
739 	ect = 0;
740 	if (*vc->vc_uni_pagedir_loc) {
741 		p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
742 		for (i = 0; i < 32; i++)
743 		if ((p1 = p->uni_pgdir[i]))
744 			for (j = 0; j < 32; j++)
745 			if ((p2 = *(p1++)))
746 				for (k = 0; k < 64; k++) {
747 					if (*p2 < MAX_GLYPH && ect++ < ct) {
748 						__put_user((u_short)((i<<11)+(j<<6)+k),
749 							   &list->unicode);
750 						__put_user((u_short) *p2,
751 							   &list->fontpos);
752 						list++;
753 					}
754 					p2++;
755 				}
756 	}
757 	__put_user(ect, uct);
758 	console_unlock();
759 	return ((ect <= ct) ? 0 : -ENOMEM);
760 }
761 
762 /*
763  * Always use USER_MAP. These functions are used by the keyboard,
764  * which shouldn't be affected by G0/G1 switching, etc.
765  * If the user map still contains default values, i.e. the
766  * direct-to-font mapping, then assume user is using Latin1.
767  *
768  * FIXME: at some point we need to decide if we want to lock the table
769  * update element itself via the keyboard_event_lock for consistency with the
770  * keyboard driver as well as the consoles
771  */
772 /* may be called during an interrupt */
773 u32 conv_8bit_to_uni(unsigned char c)
774 {
775 	unsigned short uni = translations[USER_MAP][c];
776 	return uni == (0xf000 | c) ? c : uni;
777 }
778 
779 int conv_uni_to_8bit(u32 uni)
780 {
781 	int c;
782 	for (c = 0; c < 0x100; c++)
783 		if (translations[USER_MAP][c] == uni ||
784 		   (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
785 			return c;
786 	return -1;
787 }
788 
789 int
790 conv_uni_to_pc(struct vc_data *conp, long ucs)
791 {
792 	int h;
793 	u16 **p1, *p2;
794 	struct uni_pagedir *p;
795 
796 	/* Only 16-bit codes supported at this time */
797 	if (ucs > 0xffff)
798 		return -4;		/* Not found */
799 	else if (ucs < 0x20)
800 		return -1;		/* Not a printable character */
801 	else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
802 		return -2;			/* Zero-width space */
803 	/*
804 	 * UNI_DIRECT_BASE indicates the start of the region in the User Zone
805 	 * which always has a 1:1 mapping to the currently loaded font.  The
806 	 * UNI_DIRECT_MASK indicates the bit span of the region.
807 	 */
808 	else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
809 		return ucs & UNI_DIRECT_MASK;
810 
811 	if (!*conp->vc_uni_pagedir_loc)
812 		return -3;
813 
814 	p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
815 	if ((p1 = p->uni_pgdir[ucs >> 11]) &&
816 	    (p2 = p1[(ucs >> 6) & 0x1f]) &&
817 	    (h = p2[ucs & 0x3f]) < MAX_GLYPH)
818 		return h;
819 
820 	return -4;		/* not found */
821 }
822 
823 /*
824  * This is called at sys_setup time, after memory and the console are
825  * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
826  * from this function, hence the call from sys_setup.
827  */
828 void __init
829 console_map_init(void)
830 {
831 	int i;
832 
833 	for (i = 0; i < MAX_NR_CONSOLES; i++)
834 		if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
835 			con_set_default_unimap(vc_cons[i].d);
836 }
837 
838