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