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
26static 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
174static int inv_translate[MAX_NR_CONSOLES];
175
176struct 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};
183
184static struct uni_pagedir *dflt;
185
186static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
187{
188	int j, glyph;
189	unsigned short *t = translations[i];
190	unsigned char *q;
191
192	if (!p) return;
193	q = p->inverse_translations[i];
194
195	if (!q) {
196		q = p->inverse_translations[i] = kmalloc(MAX_GLYPH, GFP_KERNEL);
197		if (!q) return;
198	}
199	memset(q, 0, MAX_GLYPH);
200
201	for (j = 0; j < E_TABSZ; j++) {
202		glyph = conv_uni_to_pc(conp, t[j]);
203		if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
204			/* prefer '-' above SHY etc. */
205		  	q[glyph] = j;
206		}
207	}
208}
209
210static void set_inverse_trans_unicode(struct vc_data *conp,
211				      struct uni_pagedir *p)
212{
213	int i, j, k, glyph;
214	u16 **p1, *p2;
215	u16 *q;
216
217	if (!p) return;
218	q = p->inverse_trans_unicode;
219	if (!q) {
220		q = p->inverse_trans_unicode =
221			kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
222		if (!q)
223			return;
224	}
225	memset(q, 0, MAX_GLYPH * sizeof(u16));
226
227	for (i = 0; i < 32; i++) {
228		p1 = p->uni_pgdir[i];
229		if (!p1)
230			continue;
231		for (j = 0; j < 32; j++) {
232			p2 = p1[j];
233			if (!p2)
234				continue;
235			for (k = 0; k < 64; k++) {
236				glyph = p2[k];
237				if (glyph >= 0 && glyph < MAX_GLYPH
238					       && q[glyph] < 32)
239		  			q[glyph] = (i << 11) + (j << 6) + k;
240			}
241		}
242	}
243}
244
245unsigned short *set_translate(int m, struct vc_data *vc)
246{
247	inv_translate[vc->vc_num] = m;
248	return translations[m];
249}
250
251/*
252 * Inverse translation is impossible for several reasons:
253 * 1. The font<->character maps are not 1-1.
254 * 2. The text may have been written while a different translation map
255 *    was active.
256 * Still, it is now possible to a certain extent to cut and paste non-ASCII.
257 */
258u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
259{
260	struct uni_pagedir *p;
261	int m;
262	if (glyph < 0 || glyph >= MAX_GLYPH)
263		return 0;
264	else if (!(p = *conp->vc_uni_pagedir_loc))
265		return glyph;
266	else if (use_unicode) {
267		if (!p->inverse_trans_unicode)
268			return glyph;
269		else
270			return p->inverse_trans_unicode[glyph];
271	} else {
272		m = inv_translate[conp->vc_num];
273		if (!p->inverse_translations[m])
274			return glyph;
275		else
276			return p->inverse_translations[m][glyph];
277	}
278}
279EXPORT_SYMBOL_GPL(inverse_translate);
280
281static void update_user_maps(void)
282{
283	int i;
284	struct uni_pagedir *p, *q = NULL;
285
286	for (i = 0; i < MAX_NR_CONSOLES; i++) {
287		if (!vc_cons_allocated(i))
288			continue;
289		p = *vc_cons[i].d->vc_uni_pagedir_loc;
290		if (p && p != q) {
291			set_inverse_transl(vc_cons[i].d, p, USER_MAP);
292			set_inverse_trans_unicode(vc_cons[i].d, p);
293			q = p;
294		}
295	}
296}
297
298/*
299 * Load customizable translation table
300 * arg points to a 256 byte translation table.
301 *
302 * The "old" variants are for translation directly to font (using the
303 * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
304 * Unicodes explicitly.
305 */
306int con_set_trans_old(unsigned char __user * arg)
307{
308	int i;
309	unsigned short *p = translations[USER_MAP];
310
311	if (!access_ok(VERIFY_READ, arg, E_TABSZ))
312		return -EFAULT;
313
314	console_lock();
315	for (i=0; i<E_TABSZ ; i++) {
316		unsigned char uc;
317		__get_user(uc, arg+i);
318		p[i] = UNI_DIRECT_BASE | uc;
319	}
320
321	update_user_maps();
322	console_unlock();
323	return 0;
324}
325
326int con_get_trans_old(unsigned char __user * arg)
327{
328	int i, ch;
329	unsigned short *p = translations[USER_MAP];
330
331	if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
332		return -EFAULT;
333
334	console_lock();
335	for (i=0; i<E_TABSZ ; i++)
336	{
337		ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
338		__put_user((ch & ~0xff) ? 0 : ch, arg+i);
339	}
340	console_unlock();
341	return 0;
342}
343
344int con_set_trans_new(ushort __user * arg)
345{
346	int i;
347	unsigned short *p = translations[USER_MAP];
348
349	if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
350		return -EFAULT;
351
352	console_lock();
353	for (i=0; i<E_TABSZ ; i++) {
354		unsigned short us;
355		__get_user(us, arg+i);
356		p[i] = us;
357	}
358
359	update_user_maps();
360	console_unlock();
361	return 0;
362}
363
364int con_get_trans_new(ushort __user * arg)
365{
366	int i;
367	unsigned short *p = translations[USER_MAP];
368
369	if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
370		return -EFAULT;
371
372	console_lock();
373	for (i=0; i<E_TABSZ ; i++)
374	  __put_user(p[i], arg+i);
375	console_unlock();
376
377	return 0;
378}
379
380/*
381 * Unicode -> current font conversion
382 *
383 * A font has at most 512 chars, usually 256.
384 * But one font position may represent several Unicode chars.
385 * A hashtable is somewhat of a pain to deal with, so use a
386 * "paged table" instead.  Simulation has shown the memory cost of
387 * this 3-level paged table scheme to be comparable to a hash table.
388 */
389
390extern u8 dfont_unicount[];	/* Defined in console_defmap.c */
391extern u16 dfont_unitable[];
392
393static void con_release_unimap(struct uni_pagedir *p)
394{
395	u16 **p1;
396	int i, j;
397
398	if (p == dflt) dflt = NULL;
399	for (i = 0; i < 32; i++) {
400		if ((p1 = p->uni_pgdir[i]) != NULL) {
401			for (j = 0; j < 32; j++)
402				kfree(p1[j]);
403			kfree(p1);
404		}
405		p->uni_pgdir[i] = NULL;
406	}
407	for (i = 0; i < 4; i++) {
408		kfree(p->inverse_translations[i]);
409		p->inverse_translations[i] = NULL;
410	}
411	kfree(p->inverse_trans_unicode);
412	p->inverse_trans_unicode = NULL;
413}
414
415/* Caller must hold the console lock */
416void con_free_unimap(struct vc_data *vc)
417{
418	struct uni_pagedir *p;
419
420	p = *vc->vc_uni_pagedir_loc;
421	if (!p)
422		return;
423	*vc->vc_uni_pagedir_loc = NULL;
424	if (--p->refcount)
425		return;
426	con_release_unimap(p);
427	kfree(p);
428}
429
430static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
431{
432	int i, j, k;
433	struct uni_pagedir *q;
434
435	for (i = 0; i < MAX_NR_CONSOLES; i++) {
436		if (!vc_cons_allocated(i))
437			continue;
438		q = *vc_cons[i].d->vc_uni_pagedir_loc;
439		if (!q || q == p || q->sum != p->sum)
440			continue;
441		for (j = 0; j < 32; j++) {
442			u16 **p1, **q1;
443			p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
444			if (!p1 && !q1)
445				continue;
446			if (!p1 || !q1)
447				break;
448			for (k = 0; k < 32; k++) {
449				if (!p1[k] && !q1[k])
450					continue;
451				if (!p1[k] || !q1[k])
452					break;
453				if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
454					break;
455			}
456			if (k < 32)
457				break;
458		}
459		if (j == 32) {
460			q->refcount++;
461			*conp->vc_uni_pagedir_loc = q;
462			con_release_unimap(p);
463			kfree(p);
464			return 1;
465		}
466	}
467	return 0;
468}
469
470static int
471con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
472{
473	int i, n;
474	u16 **p1, *p2;
475
476	if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
477		p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
478		if (!p1) return -ENOMEM;
479		for (i = 0; i < 32; i++)
480			p1[i] = NULL;
481	}
482
483	if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
484		p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
485		if (!p2) return -ENOMEM;
486		memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
487	}
488
489	p2[unicode & 0x3f] = fontpos;
490
491	p->sum += (fontpos << 20) + unicode;
492
493	return 0;
494}
495
496/* ui is a leftover from using a hashtable, but might be used again
497   Caller must hold the lock */
498static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
499{
500	struct uni_pagedir *p, *q;
501
502	p = *vc->vc_uni_pagedir_loc;
503	if (!p || --p->refcount) {
504		q = kzalloc(sizeof(*p), GFP_KERNEL);
505		if (!q) {
506			if (p)
507				p->refcount++;
508			return -ENOMEM;
509		}
510		q->refcount=1;
511		*vc->vc_uni_pagedir_loc = q;
512	} else {
513		if (p == dflt) dflt = NULL;
514		p->refcount++;
515		p->sum = 0;
516		con_release_unimap(p);
517	}
518	return 0;
519}
520
521int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
522{
523	int ret;
524	console_lock();
525	ret = con_do_clear_unimap(vc, ui);
526	console_unlock();
527	return ret;
528}
529
530int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
531{
532	int err = 0, err1, i;
533	struct uni_pagedir *p, *q;
534
535	if (!ct)
536		return 0;
537
538	console_lock();
539
540	/* Save original vc_unipagdir_loc in case we allocate a new one */
541	p = *vc->vc_uni_pagedir_loc;
542
543	if (!p) {
544		err = -EINVAL;
545
546		goto out_unlock;
547	}
548
549	if (p->refcount > 1) {
550		int j, k;
551		u16 **p1, *p2, l;
552
553		err1 = con_do_clear_unimap(vc, NULL);
554		if (err1) {
555			console_unlock();
556			return err1;
557		}
558
559		/*
560		 * Since refcount was > 1, con_clear_unimap() allocated a
561		 * a new uni_pagedir for this vc.  Re: p != q
562		 */
563		q = *vc->vc_uni_pagedir_loc;
564
565		/*
566		 * uni_pgdir is a 32*32*64 table with rows allocated
567		 * when its first entry is added.  The unicode value must
568		 * still be incremented for empty rows.  We are copying
569		 * entries from "p" (old) to "q" (new).
570		 */
571		l = 0;		/* unicode value */
572		for (i = 0; i < 32; i++)
573		if ((p1 = p->uni_pgdir[i]))
574			for (j = 0; j < 32; j++)
575			if ((p2 = p1[j])) {
576				for (k = 0; k < 64; k++, l++)
577				if (p2[k] != 0xffff) {
578					/*
579					 * Found one, copy entry for unicode
580					 * l with fontpos value p2[k].
581					 */
582					err1 = con_insert_unipair(q, l, p2[k]);
583					if (err1) {
584						p->refcount++;
585						*vc->vc_uni_pagedir_loc = p;
586						con_release_unimap(q);
587						kfree(q);
588						console_unlock();
589						return err1;
590					}
591				}
592			} else {
593				/* Account for row of 64 empty entries */
594				l += 64;
595			}
596		else
597			/* Account for empty table */
598			l += 32 * 64;
599
600		/*
601		 * Finished copying font table, set vc_uni_pagedir to new table
602		 */
603		p = q;
604	} else if (p == dflt) {
605		dflt = NULL;
606	}
607
608	/*
609	 * Insert user specified unicode pairs into new table.
610	 */
611	while (ct--) {
612		unsigned short unicode, fontpos;
613		__get_user(unicode, &list->unicode);
614		__get_user(fontpos, &list->fontpos);
615		if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
616			err = err1;
617		list++;
618	}
619
620	/*
621	 * Merge with fontmaps of any other virtual consoles.
622	 */
623	if (con_unify_unimap(vc, p)) {
624		console_unlock();
625		return err;
626	}
627
628	for (i = 0; i <= 3; i++)
629		set_inverse_transl(vc, p, i); /* Update inverse translations */
630	set_inverse_trans_unicode(vc, p);
631
632out_unlock:
633	console_unlock();
634	return err;
635}
636
637/**
638 *	con_set_default_unimap	-	set default unicode map
639 *	@vc: the console we are updating
640 *
641 *	Loads the unimap for the hardware font, as defined in uni_hash.tbl.
642 *	The representation used was the most compact I could come up
643 *	with.  This routine is executed at video setup, and when the
644 *	PIO_FONTRESET ioctl is called.
645 *
646 *	The caller must hold the console lock
647 */
648int con_set_default_unimap(struct vc_data *vc)
649{
650	int i, j, err = 0, err1;
651	u16 *q;
652	struct uni_pagedir *p;
653
654	if (dflt) {
655		p = *vc->vc_uni_pagedir_loc;
656		if (p == dflt)
657			return 0;
658
659		dflt->refcount++;
660		*vc->vc_uni_pagedir_loc = dflt;
661		if (p && !--p->refcount) {
662			con_release_unimap(p);
663			kfree(p);
664		}
665		return 0;
666	}
667
668	/* The default font is always 256 characters */
669
670	err = con_do_clear_unimap(vc, NULL);
671	if (err)
672		return err;
673
674	p = *vc->vc_uni_pagedir_loc;
675	q = dfont_unitable;
676
677	for (i = 0; i < 256; i++)
678		for (j = dfont_unicount[i]; j; j--) {
679			err1 = con_insert_unipair(p, *(q++), i);
680			if (err1)
681				err = err1;
682		}
683
684	if (con_unify_unimap(vc, p)) {
685		dflt = *vc->vc_uni_pagedir_loc;
686		return err;
687	}
688
689	for (i = 0; i <= 3; i++)
690		set_inverse_transl(vc, p, i);	/* Update all inverse translations */
691	set_inverse_trans_unicode(vc, p);
692	dflt = p;
693	return err;
694}
695EXPORT_SYMBOL(con_set_default_unimap);
696
697/**
698 *	con_copy_unimap		-	copy unimap between two vts
699 *	@dst_vc: target
700 *	@src_vt: source
701 *
702 *	The caller must hold the console lock when invoking this method
703 */
704int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
705{
706	struct uni_pagedir *q;
707
708	if (!*src_vc->vc_uni_pagedir_loc)
709		return -EINVAL;
710	if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
711		return 0;
712	con_free_unimap(dst_vc);
713	q = *src_vc->vc_uni_pagedir_loc;
714	q->refcount++;
715	*dst_vc->vc_uni_pagedir_loc = q;
716	return 0;
717}
718EXPORT_SYMBOL(con_copy_unimap);
719
720/**
721 *	con_get_unimap		-	get the unicode map
722 *	@vc: the console to read from
723 *
724 *	Read the console unicode data for this console. Called from the ioctl
725 *	handlers.
726 */
727int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
728{
729	int i, j, k, ect;
730	u16 **p1, *p2;
731	struct uni_pagedir *p;
732
733	console_lock();
734
735	ect = 0;
736	if (*vc->vc_uni_pagedir_loc) {
737		p = *vc->vc_uni_pagedir_loc;
738		for (i = 0; i < 32; i++)
739		if ((p1 = p->uni_pgdir[i]))
740			for (j = 0; j < 32; j++)
741			if ((p2 = *(p1++)))
742				for (k = 0; k < 64; k++) {
743					if (*p2 < MAX_GLYPH && ect++ < ct) {
744						__put_user((u_short)((i<<11)+(j<<6)+k),
745							   &list->unicode);
746						__put_user((u_short) *p2,
747							   &list->fontpos);
748						list++;
749					}
750					p2++;
751				}
752	}
753	__put_user(ect, uct);
754	console_unlock();
755	return ((ect <= ct) ? 0 : -ENOMEM);
756}
757
758/*
759 * Always use USER_MAP. These functions are used by the keyboard,
760 * which shouldn't be affected by G0/G1 switching, etc.
761 * If the user map still contains default values, i.e. the
762 * direct-to-font mapping, then assume user is using Latin1.
763 *
764 * FIXME: at some point we need to decide if we want to lock the table
765 * update element itself via the keyboard_event_lock for consistency with the
766 * keyboard driver as well as the consoles
767 */
768/* may be called during an interrupt */
769u32 conv_8bit_to_uni(unsigned char c)
770{
771	unsigned short uni = translations[USER_MAP][c];
772	return uni == (0xf000 | c) ? c : uni;
773}
774
775int conv_uni_to_8bit(u32 uni)
776{
777	int c;
778	for (c = 0; c < 0x100; c++)
779		if (translations[USER_MAP][c] == uni ||
780		   (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
781			return c;
782	return -1;
783}
784
785int
786conv_uni_to_pc(struct vc_data *conp, long ucs)
787{
788	int h;
789	u16 **p1, *p2;
790	struct uni_pagedir *p;
791
792	/* Only 16-bit codes supported at this time */
793	if (ucs > 0xffff)
794		return -4;		/* Not found */
795	else if (ucs < 0x20)
796		return -1;		/* Not a printable character */
797	else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
798		return -2;			/* Zero-width space */
799	/*
800	 * UNI_DIRECT_BASE indicates the start of the region in the User Zone
801	 * which always has a 1:1 mapping to the currently loaded font.  The
802	 * UNI_DIRECT_MASK indicates the bit span of the region.
803	 */
804	else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
805		return ucs & UNI_DIRECT_MASK;
806
807	if (!*conp->vc_uni_pagedir_loc)
808		return -3;
809
810	p = *conp->vc_uni_pagedir_loc;
811	if ((p1 = p->uni_pgdir[ucs >> 11]) &&
812	    (p2 = p1[(ucs >> 6) & 0x1f]) &&
813	    (h = p2[ucs & 0x3f]) < MAX_GLYPH)
814		return h;
815
816	return -4;		/* not found */
817}
818
819/*
820 * This is called at sys_setup time, after memory and the console are
821 * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
822 * from this function, hence the call from sys_setup.
823 */
824void __init
825console_map_init(void)
826{
827	int i;
828
829	for (i = 0; i < MAX_NR_CONSOLES; i++)
830		if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
831			con_set_default_unimap(vc_cons[i].d);
832}
833
834