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