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