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