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