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