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