xref: /openbmc/linux/drivers/tty/vt/consolemap.c (revision 74ce1896)
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 	unsigned char ubuf[E_TABSZ];
326 
327 	if (copy_from_user(ubuf, arg, E_TABSZ))
328 		return -EFAULT;
329 
330 	for (i = 0; i < E_TABSZ ; i++)
331 		inbuf[i] = UNI_DIRECT_BASE | ubuf[i];
332 
333 	console_lock();
334 	memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
335 	update_user_maps();
336 	console_unlock();
337 	return 0;
338 }
339 
340 int con_get_trans_old(unsigned char __user * arg)
341 {
342 	int i, ch;
343 	unsigned short *p = translations[USER_MAP];
344 	unsigned char outbuf[E_TABSZ];
345 
346 	console_lock();
347 	for (i = 0; i < E_TABSZ ; i++)
348 	{
349 		ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
350 		outbuf[i] = (ch & ~0xff) ? 0 : ch;
351 	}
352 	console_unlock();
353 
354 	return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 0;
355 }
356 
357 int con_set_trans_new(ushort __user * arg)
358 {
359 	unsigned short inbuf[E_TABSZ];
360 
361 	if (copy_from_user(inbuf, arg, sizeof(inbuf)))
362 		return -EFAULT;
363 
364 	console_lock();
365 	memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
366 	update_user_maps();
367 	console_unlock();
368 	return 0;
369 }
370 
371 int con_get_trans_new(ushort __user * arg)
372 {
373 	unsigned short outbuf[E_TABSZ];
374 
375 	console_lock();
376 	memcpy(outbuf, translations[USER_MAP], sizeof(outbuf));
377 	console_unlock();
378 
379 	return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 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 		p1 = p->uni_pgdir[i];
403 		if (p1 != NULL) {
404 			for (j = 0; j < 32; j++)
405 				kfree(p1[j]);
406 			kfree(p1);
407 		}
408 		p->uni_pgdir[i] = NULL;
409 	}
410 	for (i = 0; i < 4; i++) {
411 		kfree(p->inverse_translations[i]);
412 		p->inverse_translations[i] = NULL;
413 	}
414 	kfree(p->inverse_trans_unicode);
415 	p->inverse_trans_unicode = NULL;
416 }
417 
418 /* Caller must hold the console lock */
419 void con_free_unimap(struct vc_data *vc)
420 {
421 	struct uni_pagedir *p;
422 
423 	p = *vc->vc_uni_pagedir_loc;
424 	if (!p)
425 		return;
426 	*vc->vc_uni_pagedir_loc = NULL;
427 	if (--p->refcount)
428 		return;
429 	con_release_unimap(p);
430 	kfree(p);
431 }
432 
433 static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
434 {
435 	int i, j, k;
436 	struct uni_pagedir *q;
437 
438 	for (i = 0; i < MAX_NR_CONSOLES; i++) {
439 		if (!vc_cons_allocated(i))
440 			continue;
441 		q = *vc_cons[i].d->vc_uni_pagedir_loc;
442 		if (!q || q == p || q->sum != p->sum)
443 			continue;
444 		for (j = 0; j < 32; j++) {
445 			u16 **p1, **q1;
446 			p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
447 			if (!p1 && !q1)
448 				continue;
449 			if (!p1 || !q1)
450 				break;
451 			for (k = 0; k < 32; k++) {
452 				if (!p1[k] && !q1[k])
453 					continue;
454 				if (!p1[k] || !q1[k])
455 					break;
456 				if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
457 					break;
458 			}
459 			if (k < 32)
460 				break;
461 		}
462 		if (j == 32) {
463 			q->refcount++;
464 			*conp->vc_uni_pagedir_loc = q;
465 			con_release_unimap(p);
466 			kfree(p);
467 			return 1;
468 		}
469 	}
470 	return 0;
471 }
472 
473 static int
474 con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
475 {
476 	int i, n;
477 	u16 **p1, *p2;
478 
479 	p1 = p->uni_pgdir[n = unicode >> 11];
480 	if (!p1) {
481 		p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
482 		if (!p1) return -ENOMEM;
483 		for (i = 0; i < 32; i++)
484 			p1[i] = NULL;
485 	}
486 
487 	p2 = p1[n = (unicode >> 6) & 0x1f];
488 	if (!p2) {
489 		p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
490 		if (!p2) return -ENOMEM;
491 		memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
492 	}
493 
494 	p2[unicode & 0x3f] = fontpos;
495 
496 	p->sum += (fontpos << 20) + unicode;
497 
498 	return 0;
499 }
500 
501 /* Caller must hold the lock */
502 static int con_do_clear_unimap(struct vc_data *vc)
503 {
504 	struct uni_pagedir *p, *q;
505 
506 	p = *vc->vc_uni_pagedir_loc;
507 	if (!p || --p->refcount) {
508 		q = kzalloc(sizeof(*p), GFP_KERNEL);
509 		if (!q) {
510 			if (p)
511 				p->refcount++;
512 			return -ENOMEM;
513 		}
514 		q->refcount=1;
515 		*vc->vc_uni_pagedir_loc = q;
516 	} else {
517 		if (p == dflt) dflt = NULL;
518 		p->refcount++;
519 		p->sum = 0;
520 		con_release_unimap(p);
521 	}
522 	return 0;
523 }
524 
525 int con_clear_unimap(struct vc_data *vc)
526 {
527 	int ret;
528 	console_lock();
529 	ret = con_do_clear_unimap(vc);
530 	console_unlock();
531 	return ret;
532 }
533 
534 int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
535 {
536 	int err = 0, err1, i;
537 	struct uni_pagedir *p, *q;
538 	struct unipair *unilist, *plist;
539 
540 	if (!ct)
541 		return 0;
542 
543 	unilist = memdup_user(list, ct * sizeof(struct unipair));
544 	if (IS_ERR(unilist))
545 		return PTR_ERR(unilist);
546 
547 	console_lock();
548 
549 	/* Save original vc_unipagdir_loc in case we allocate a new one */
550 	p = *vc->vc_uni_pagedir_loc;
551 
552 	if (!p) {
553 		err = -EINVAL;
554 
555 		goto out_unlock;
556 	}
557 
558 	if (p->refcount > 1) {
559 		int j, k;
560 		u16 **p1, *p2, l;
561 
562 		err1 = con_do_clear_unimap(vc);
563 		if (err1) {
564 			err = err1;
565 			goto out_unlock;
566 		}
567 
568 		/*
569 		 * Since refcount was > 1, con_clear_unimap() allocated a
570 		 * a new uni_pagedir for this vc.  Re: p != q
571 		 */
572 		q = *vc->vc_uni_pagedir_loc;
573 
574 		/*
575 		 * uni_pgdir is a 32*32*64 table with rows allocated
576 		 * when its first entry is added.  The unicode value must
577 		 * still be incremented for empty rows.  We are copying
578 		 * entries from "p" (old) to "q" (new).
579 		 */
580 		l = 0;		/* unicode value */
581 		for (i = 0; i < 32; i++) {
582 		p1 = p->uni_pgdir[i];
583 		if (p1)
584 			for (j = 0; j < 32; j++) {
585 			p2 = p1[j];
586 			if (p2) {
587 				for (k = 0; k < 64; k++, l++)
588 				if (p2[k] != 0xffff) {
589 					/*
590 					 * Found one, copy entry for unicode
591 					 * l with fontpos value p2[k].
592 					 */
593 					err1 = con_insert_unipair(q, l, p2[k]);
594 					if (err1) {
595 						p->refcount++;
596 						*vc->vc_uni_pagedir_loc = p;
597 						con_release_unimap(q);
598 						kfree(q);
599 						err = err1;
600 						goto out_unlock;
601 					}
602 				}
603 			} else {
604 				/* Account for row of 64 empty entries */
605 				l += 64;
606 			}
607 		}
608 		else
609 			/* Account for empty table */
610 			l += 32 * 64;
611 		}
612 
613 		/*
614 		 * Finished copying font table, set vc_uni_pagedir to new table
615 		 */
616 		p = q;
617 	} else if (p == dflt) {
618 		dflt = NULL;
619 	}
620 
621 	/*
622 	 * Insert user specified unicode pairs into new table.
623 	 */
624 	for (plist = unilist; ct; ct--, plist++) {
625 		err1 = con_insert_unipair(p, plist->unicode, plist->fontpos);
626 		if (err1)
627 			err = err1;
628 	}
629 
630 	/*
631 	 * Merge with fontmaps of any other virtual consoles.
632 	 */
633 	if (con_unify_unimap(vc, p))
634 		goto out_unlock;
635 
636 	for (i = 0; i <= 3; i++)
637 		set_inverse_transl(vc, p, i); /* Update inverse translations */
638 	set_inverse_trans_unicode(vc, p);
639 
640 out_unlock:
641 	console_unlock();
642 	kfree(unilist);
643 	return err;
644 }
645 
646 /**
647  *	con_set_default_unimap	-	set default unicode map
648  *	@vc: the console we are updating
649  *
650  *	Loads the unimap for the hardware font, as defined in uni_hash.tbl.
651  *	The representation used was the most compact I could come up
652  *	with.  This routine is executed at video setup, and when the
653  *	PIO_FONTRESET ioctl is called.
654  *
655  *	The caller must hold the console lock
656  */
657 int con_set_default_unimap(struct vc_data *vc)
658 {
659 	int i, j, err = 0, err1;
660 	u16 *q;
661 	struct uni_pagedir *p;
662 
663 	if (dflt) {
664 		p = *vc->vc_uni_pagedir_loc;
665 		if (p == dflt)
666 			return 0;
667 
668 		dflt->refcount++;
669 		*vc->vc_uni_pagedir_loc = dflt;
670 		if (p && !--p->refcount) {
671 			con_release_unimap(p);
672 			kfree(p);
673 		}
674 		return 0;
675 	}
676 
677 	/* The default font is always 256 characters */
678 
679 	err = con_do_clear_unimap(vc);
680 	if (err)
681 		return err;
682 
683 	p = *vc->vc_uni_pagedir_loc;
684 	q = dfont_unitable;
685 
686 	for (i = 0; i < 256; i++)
687 		for (j = dfont_unicount[i]; j; j--) {
688 			err1 = con_insert_unipair(p, *(q++), i);
689 			if (err1)
690 				err = err1;
691 		}
692 
693 	if (con_unify_unimap(vc, p)) {
694 		dflt = *vc->vc_uni_pagedir_loc;
695 		return err;
696 	}
697 
698 	for (i = 0; i <= 3; i++)
699 		set_inverse_transl(vc, p, i);	/* Update all inverse translations */
700 	set_inverse_trans_unicode(vc, p);
701 	dflt = p;
702 	return err;
703 }
704 EXPORT_SYMBOL(con_set_default_unimap);
705 
706 /**
707  *	con_copy_unimap		-	copy unimap between two vts
708  *	@dst_vc: target
709  *	@src_vt: source
710  *
711  *	The caller must hold the console lock when invoking this method
712  */
713 int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
714 {
715 	struct uni_pagedir *q;
716 
717 	if (!*src_vc->vc_uni_pagedir_loc)
718 		return -EINVAL;
719 	if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
720 		return 0;
721 	con_free_unimap(dst_vc);
722 	q = *src_vc->vc_uni_pagedir_loc;
723 	q->refcount++;
724 	*dst_vc->vc_uni_pagedir_loc = q;
725 	return 0;
726 }
727 EXPORT_SYMBOL(con_copy_unimap);
728 
729 /**
730  *	con_get_unimap		-	get the unicode map
731  *	@vc: the console to read from
732  *
733  *	Read the console unicode data for this console. Called from the ioctl
734  *	handlers.
735  */
736 int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
737 {
738 	int i, j, k, ret = 0;
739 	ushort ect;
740 	u16 **p1, *p2;
741 	struct uni_pagedir *p;
742 	struct unipair *unilist;
743 
744 	unilist = kmalloc_array(ct, sizeof(struct unipair), GFP_KERNEL);
745 	if (!unilist)
746 		return -ENOMEM;
747 
748 	console_lock();
749 
750 	ect = 0;
751 	if (*vc->vc_uni_pagedir_loc) {
752 		p = *vc->vc_uni_pagedir_loc;
753 		for (i = 0; i < 32; i++) {
754 		p1 = p->uni_pgdir[i];
755 		if (p1)
756 			for (j = 0; j < 32; j++) {
757 			p2 = *(p1++);
758 			if (p2)
759 				for (k = 0; k < 64; k++, p2++) {
760 					if (*p2 >= MAX_GLYPH)
761 						continue;
762 					if (ect < ct) {
763 						unilist[ect].unicode =
764 							(i<<11)+(j<<6)+k;
765 						unilist[ect].fontpos = *p2;
766 					}
767 					ect++;
768 				}
769 			}
770 		}
771 	}
772 	console_unlock();
773 	if (copy_to_user(list, unilist, min(ect, ct) * sizeof(struct unipair)))
774 		ret = -EFAULT;
775 	put_user(ect, uct);
776 	kfree(unilist);
777 	return ret ? ret : (ect <= ct) ? 0 : -ENOMEM;
778 }
779 
780 /*
781  * Always use USER_MAP. These functions are used by the keyboard,
782  * which shouldn't be affected by G0/G1 switching, etc.
783  * If the user map still contains default values, i.e. the
784  * direct-to-font mapping, then assume user is using Latin1.
785  *
786  * FIXME: at some point we need to decide if we want to lock the table
787  * update element itself via the keyboard_event_lock for consistency with the
788  * keyboard driver as well as the consoles
789  */
790 /* may be called during an interrupt */
791 u32 conv_8bit_to_uni(unsigned char c)
792 {
793 	unsigned short uni = translations[USER_MAP][c];
794 	return uni == (0xf000 | c) ? c : uni;
795 }
796 
797 int conv_uni_to_8bit(u32 uni)
798 {
799 	int c;
800 	for (c = 0; c < 0x100; c++)
801 		if (translations[USER_MAP][c] == uni ||
802 		   (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
803 			return c;
804 	return -1;
805 }
806 
807 int
808 conv_uni_to_pc(struct vc_data *conp, long ucs)
809 {
810 	int h;
811 	u16 **p1, *p2;
812 	struct uni_pagedir *p;
813 
814 	/* Only 16-bit codes supported at this time */
815 	if (ucs > 0xffff)
816 		return -4;		/* Not found */
817 	else if (ucs < 0x20)
818 		return -1;		/* Not a printable character */
819 	else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
820 		return -2;			/* Zero-width space */
821 	/*
822 	 * UNI_DIRECT_BASE indicates the start of the region in the User Zone
823 	 * which always has a 1:1 mapping to the currently loaded font.  The
824 	 * UNI_DIRECT_MASK indicates the bit span of the region.
825 	 */
826 	else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
827 		return ucs & UNI_DIRECT_MASK;
828 
829 	if (!*conp->vc_uni_pagedir_loc)
830 		return -3;
831 
832 	p = *conp->vc_uni_pagedir_loc;
833 	if ((p1 = p->uni_pgdir[ucs >> 11]) &&
834 	    (p2 = p1[(ucs >> 6) & 0x1f]) &&
835 	    (h = p2[ucs & 0x3f]) < MAX_GLYPH)
836 		return h;
837 
838 	return -4;		/* not found */
839 }
840 
841 /*
842  * This is called at sys_setup time, after memory and the console are
843  * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
844  * from this function, hence the call from sys_setup.
845  */
846 void __init
847 console_map_init(void)
848 {
849 	int i;
850 
851 	for (i = 0; i < MAX_NR_CONSOLES; i++)
852 		if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
853 			con_set_default_unimap(vc_cons[i].d);
854 }
855 
856